Skip to content

feat: generic runtime opts and native tool-call compat for GLM/Laguna/MiniMax - #138

Merged
Qubitium merged 8 commits into
mainfrom
feat/runtime-opts-toolcall-compat
Aug 24, 2026
Merged

feat: generic runtime opts and native tool-call compat for GLM/Laguna/MiniMax#138
Qubitium merged 8 commits into
mainfrom
feat/runtime-opts-toolcall-compat

Conversation

@Qubitium

Copy link
Copy Markdown
Contributor

Summary

Two additions on top of the merged agent-runtime work:

  1. Generic opts on every runtime. Runtime-specific knobs (memory, CPUs, disk, networking, GPU) go through a validated opts mapping instead of bespoke constructor kwargs. Keys are checked against a per-runtime allowlist at construction — unknown keys raise, so a typo can never silently weaken sandbox semantics.
  2. Native tool-call compatibility audit against the real chat templates of the requested model families, with parser coverage and fixtures for each encoding.

Runtime opts

opt DockerAgentRuntime SmolVmAgentRuntime
network network mode string (none/bridge/host, default none) bool → --net (default off)
memory --memory 4g --mem 4096 (MiB)
cpus --cpus 2 --cpus 2
disk --storage-opt size=20g --storage 20 (GiB)
extras gpus, shm_size allow_hosts[] (implies --net), gpu

Unknown keys raise ValueError: ... does not support opts ....

DockerAgentRuntime(opts={"memory": "8g", "cpus": 4, "pull": "missing"})
SmolVmAgentRuntime(opts={"cpus": 2, "memory": 2048, "disk": 20})

Tool-calling template compatibility

Audited against the actual chat templates on disk:

Model family Native tool-call encoding Parser
Llama 3.x Instruct <|python_tag|>{JSON} / bare JSON native_json
Qwen3 / Hermes-family <tool_call>{JSON}</tool_call> native_json
GLM-5.2 (Z.ai) <tool_call>{fn}<arg_key>k</arg_key><arg_value>v</arg_value></tool_call> ✅ new XML-args parsing
Laguna-S-2.1 same GLM XML style (verified in its chat_template.jinja) ✅ new
MiniMax-M3 <tool_call><invoke name="..."><param>v</param></invoke></tool_call> ✅ new invoke-block parsing
DeepSeek-V4-Flash ships no chat template prompted mode (<tool_call></tool_call> markers)

Lenient decoding repairs model-emitted invalid JSON escapes (e.g. \$ around shell vars); balanced-brace scanning ignores surrounding prose.

Tests

  • Opts argv matrix for both runtimes + unknown-opt rejection (40 runtime tests total)
  • Per-family native parsing fixtures replicating each template's exact emit format, incl. mixed-family generations
  • Full sweep: 105 unit tests passed, all four e2e tests (native Llama / prompted Falcon / fenced / smolvm microVM) passing repeatedly

- Add evalution/agent_runtime.py with BaseAgentRuntime, DockerAgentRuntime,
  SmolVmAgentRuntime, and UnsafeLocalRuntime.
- Add AgentRuntimeConfig in evalution/config.py and wire local tool-calling
  agentic suites to it.
- Refuse to evaluate tool-calling suites without a configured runtime; host
  execution requires explicit UnsafeLocalRuntime which warns on construction.
- Replace the Docker sandbox helper with command extraction only; scoring now
  runs through the configured runtime.
- Document agent runtimes and sandboxing usage in README.
- Update tests for runtimes, CLI construction, guard behavior, and warnings.
…entrally

- Add is_agentic and has_tool_calling ClassVar declarations to BaseTestSuite.
- Flag all agentic scaffolds is_agentic=True; local Harbor suites also set
  has_tool_calling=True.
- Move the tool-calling security guard into BaseTestSuite.evaluate so any
  suite declaring has_tool_calling requires a configured AgentRuntime,
  regardless of construction path (Python or YAML).
- Drop the now-redundant evaluate() override in _LocalAgenticBenchmark.
- Add flag coverage and central-enforcement regression tests; document the
  flags in the README Agent Runtimes section.
…e-resume tool loop

- Move path and image onto BaseAgentRuntime; path defaults to "auto" which
  resolves the runtime binary from the environment PATH.
- Replace docker_path/smolvm_path kwargs with the shared path kwarg.
- Drop suite-level docker_image/docker_timeout; runtime config owns image and
  timeout, with per-task task.toml images still overriding per call.
- Add an intercept-execute-resume tool loop to local agentic suites: explicit
  tool calls (fenced bash blocks or <bash> tags) execute on the configured
  runtime, the observation is appended, and inference resumes until a final
  answer or max_tool_turns.
- Support apply_chat_template=True for message-based multi-turn tool loops.
- Add try_extract_command for deterministic loop termination.
- Add E2E tests running Llama-3.2-1B-Instruct through a real Terminal-Bench
  task on Docker (passes) and smolvm (skips without bootable KVM); the task
  command only prints the expected answer inside an Alpine runtime, proving
  execution is not local.
- Update unit tests for scripted multi-turn sessions, auto path resolution,
  image defaults, loop interception/resume, and turn-cap termination.
- Prepare the Alpine rootfs by docker-exporting into a world-traversable
  directory: smolvm's per-VM uid isolation (uid 2000005) cannot traverse
  0700 pytest tmp dirs, and re-pulling registry images fails offline.
- Preserve executable bits when opening up permissions; blanket chmod broke
  guest exec.
- Replace the skipif heuristic with a real boot probe fixture so the test
  only skips when a microVM genuinely cannot start.
- Verified end-to-end on this host: Llama-3.2-1B-Instruct completes the
  Terminal-Bench task through both DockerAgentRuntime and SmolVmAgentRuntime;
  the guest kernel differs from the host, confirming VM execution.
…ened runtime config

Tool calling vs code output:
- Add evalution/benchmarks/tool_calling.py with declared protocols; only the
  declared protocol is intercepted, so plain code output (fenced snippets,
  prose) is inert model text and never executed.
- Replace the merged extractor with per-protocol parsing: bash_tags captures
  all <bash></bash> markers (document order, case-insensitive, empty/unclosed
  rejected); fenced_shell only executes shell-language fences with console
  prompt stripping; native_json parses <|python_tag|>{...},
  <tool_call>{...}</tool_call>, and bare JSON responses.

Native vs prompted models:
- GenerationRequest gains a tools field, threaded into chat-template rendering.
- Suites declare tool_call_mode=auto|native|prompted; auto probes the chat
  template for native tool support and uses the model's pre-trained format
  explicitly, falling back to the generic prompted <bash></bash> syntax
  (injected as a system message) for models without native tools.
- Invalid mode/format combinations fail fast at resolve time.

Config flattening:
- Drop AgentRuntimeConfig; suites take agent_runtime=DockerAgentRuntime()
  directly. BaseAgentRuntime carries shared path/image settings.

E2E coverage:
- Native: Llama-3.2-1B-Instruct completes a Terminal-Bench task via its
  pre-trained tool template through Docker and smolvm runtimes.
- Prompted: Falcon-H1-3B-Instruct (no native tools) completes it via prompted
  <bash></bash> markers.
- Fenced-shell variant kept for explicit protocol opt-in.

Strict security tests:
- Source tripwire forbids subprocess/os.system/os.popen/Popen/exec/eval in
  benchmark modules.
- Code output is never executed under the default protocol; 100% of declared
  tool calls route to the runtime with task images forwarded.
- Mode resolution matrix incl. forced-native-without-support failing closed.

Also normalize the pypcre dependency spelling (same PyPI distribution).
…ive parsing

- Replace the permissive bash-tag protocol with strict <tool_call></tool_call>
  action markers (tool_call_tags): ordinary <bash>/fenced code output can no
  longer be mistaken for a tool call.
- Capture every marker per generation in document order; a truncated final
  call (opening marker cut at generation stop) still counts; empty markers are
  dropped; special-token trailers (<|im_end|> etc.) are stripped from bodies.
- Harden the prompted system message (mandatory-marker wording) after live
  compliance testing with Falcon-H1-3B-Instruct.
- Native parser: balanced-brace JSON scan plus lenient escape repair for
  model-emitted invalid escapes (e.g. backslash-before-dollar); covers
  python_tag, Hermes-style XML, and bare JSON encodings.
- Resume turns withhold the tool schema and request verbatim output so small
  models conclude instead of issuing further calls.
- E2E task switched to a deterministic single-character runtime probe
  (0 inside Alpine, 1 on host); native/prompted/fenced/smolvm all pass
  repeatedly with real Llama-3.2-1B-Instruct and Falcon-H1-3B-Instruct.
…/MiniMax

Runtime opts:
- BaseAgentRuntime gains opts with per-runtime ALLOWED_OPTS allowlists;
  unknown keys raise at construction so typos never weaken the sandbox.
- DockerAgentRuntime maps memory/cpus/disk/gpus/shm_size/network/pull to
  --memory/--cpus/--storage-opt size/--gpus/--shm-size/--network/--pull.
- SmolVmAgentRuntime maps cpus/memory(MiB)/disk(GiB)/gpu/network/allow_hosts
  to --cpus/--mem/--storage/--gpu/--net/--allow-host.
- shell moves to the shared base config; old network/pull kwargs are replaced
  by opts entries.

Native tool-call compatibility (audited against real chat templates on disk):
- MiniMax-M3: <tool_call><invoke name=...><param>v</param>...</invoke></tool_call>
- GLM-5.2 / Laguna-S-2.1: <tool_call>{fn}<arg_key>k</arg_key><arg_value>v</arg_value></tool_call>
- DeepSeek-V4-Flash ships no chat template => prompted mode (documented).
- Parser fixtures replicate each family's exact emit format.

Tests: opts argv matrix + unknown-opt rejection; per-family native parsing
fixtures incl. mixed-generation capture; all existing suites updated.
@Qubitium
Qubitium merged commit 39b87c6 into main Aug 24, 2026
2 checks passed
@Qubitium
Qubitium deleted the feat/runtime-opts-toolcall-compat branch August 24, 2026 11:51
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.

1 participant