Skip to content

feat(onboard): bake secondary agents via NEMOCLAW_EXTRA_AGENTS_JSON - #4670

Closed
sandl99 wants to merge 5 commits into
mainfrom
sdang/reopen-4653-extra-agents
Closed

feat(onboard): bake secondary agents via NEMOCLAW_EXTRA_AGENTS_JSON#4670
sandl99 wants to merge 5 commits into
mainfrom
sdang/reopen-4653-extra-agents

Conversation

@sandl99

@sandl99 sandl99 commented Jun 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

Replaces #4653 with the same diff on a fresh upstream branch so E2E can be dispatched against the replacement PR. Adds NEMOCLAW_EXTRA_AGENTS_JSON so operators can bake one or more OpenClaw secondary agents into the sandbox openclaw.json at onboard time, while keeping the canonical main agent first and default.

Related Issue

Closes #4560.
Closes #4562 — complementary to #4560.

Changes

  • scripts/generate-openclaw-config.mts: validate NEMOCLAW_EXTRA_AGENTS_JSON_B64 — id regex, reserved-id main rejection, duplicate-id rejection, resolve()-based containment under /sandbox/.openclaw/, required per-agent tools allow/deny policy, required subagents.maxSpawnDepth, no default: true overrides, and canonical agents.list emission with main first.
  • src/lib/onboard/dockerfile-patch.ts: read NEMOCLAW_EXTRA_AGENTS_JSON and base64-encode the raw payload into ARG NEMOCLAW_EXTRA_AGENTS_JSON_B64 so build-time validation remains the single structured validation path.
  • Dockerfile: declare and promote NEMOCLAW_EXTRA_AGENTS_JSON_B64 using the existing NEMOCLAW_*_B64 convention.
  • test/generate-openclaw-config.test.ts and src/lib/onboard/dockerfile-patch-extra-agents.test.ts: add coverage for default-only emission, valid extras, reserved IDs, duplicate IDs, path traversal, required fields, field allowlists, and malformed host payload passthrough.
  • docs/reference/commands.mdx: document the extra-agent schema, constraints, validation rules, and example payload.

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Verification

  • npx prek run --all-files passes
  • npm test passes
  • Tests added or updated for new or changed behavior
  • No secrets, API keys, or credentials committed
  • Docs updated for user-facing behavior changes
  • npm run docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Note: local checks were not rerun for this replacement branch; it copies #4653 unchanged. The original #4653 PR checks were green, and this PR is intended to enable the trusted E2E rerun path.


Signed-off-by: San Dang sdang@nvidia.com

Summary by CodeRabbit

  • New Features

    • Added support for configuring additional OpenClaw agents through environment variable injection during container build; includes strict validation and automatic baking into the image configuration.
  • Documentation

    • New reference documentation covering extra agent configuration, required fields, validation rules, and usage examples.
  • Tests

    • Comprehensive test coverage for extra agent configuration patching and validation logic.

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
Signed-off-by: Tinson Lai <tinsonl@nvidia.com>

# Conflicts:
#	docs/reference/commands.mdx
…uild

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
… agents

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
@sandl99 sandl99 added integration: openclaw OpenClaw integration behavior enhancement: feature labels Jun 2, 2026
@sandl99 sandl99 self-assigned this Jun 2, 2026
@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR enables operators to define secondary OpenClaw agents via the NEMOCLAW_EXTRA_AGENTS_JSON environment variable. The feature encodes agent configuration through Docker build args, validates it against strict security rules (reserved ids, absolute paths, canonical containment), and bakes the validated agents into agents.list while preserving the primary main agent as the default.

Changes

Extra OpenClaw agents feature

Layer / File(s) Summary
Docker build contract and Dockerfile patching
Dockerfile, src/lib/onboard/dockerfile-patch.ts, src/lib/onboard/dockerfile-patch-extra-agents.test.ts
Dockerfile declares NEMOCLAW_EXTRA_AGENTS_JSON_B64 build arg with default W10= (empty JSON array) and ENV propagation; patchStagedDockerfile reads NEMOCLAW_EXTRA_AGENTS_JSON from process.env, base64-encodes the trimmed raw value after sanitization, and writes it into the Dockerfile ARG; test suite verifies JSON round-tripping, default preservation on unset input, and malformed payload passthrough.
User documentation and feature specification
docs/reference/commands.mdx
Environment variable table entry and comprehensive "Extra OpenClaw agents" section describing required entry fields, canonical primary-agent behavior, build-time validation failure on malformed/invalid JSON, detailed field constraints (ID format/uniqueness, workspace/agentDir absolute paths, tool allow/deny structure, subagent spawn depth), allowlisted keys, and example JSON payload.
Config generation implementation: validation and agents.list construction
scripts/generate-openclaw-config.mts
Decodes NEMOCLAW_EXTRA_AGENTS_JSON_B64 from base64 (defaults to empty array), validates extra agents against allowlisted schema enforcing reserved main id, absolute paths, canonical slot containment under /sandbox/.openclaw, well-formed tool policies, and subagent depth; buildAgentsList prepends canonical main entry (id, workspace, agentDir, default:true) before validated extras; buildConfig integrates validation and list building into the agents config section.
Config generation test coverage: validation rules and contracts
test/generate-openclaw-config.test.ts
Tests verify agents.list always exists with main as first default entry, append decoded extras in order, and preserve main as sole default; validation tests reject reserved/invalid/duplicate ids, enforce default: false on extras, reject relative paths and escape attempts, enforce canonical /sandbox/.openclaw/workspace-<id> and /sandbox/.openclaw/agents/<id> slot paths with dot-segment containment, validate tools and subagents structures; security tests reject credential-like keys inside tools/subagents and model overrides; canonicalization tests verify dot-segment normalization; allowlisting tests confirm unrecognized fields are stripped on write; contract test simulates OpenClaw's default-agent resolution over the baked list.

Sequence Diagram

sequenceDiagram
  participant Operator
  participant NemoClaw as NemoClaw onboard
  participant patchStagedDockerfile
  participant Dockerfile
  participant generateOpenclawConfig as generate-openclaw-config.mts
  participant OpencloConf as openclaw.json
  
  Operator->>NemoClaw: NEMOCLAW_EXTRA_AGENTS_JSON env var
  NemoClaw->>patchStagedDockerfile: staged Dockerfile + env var
  patchStagedDockerfile->>Dockerfile: patch ARG NEMOCLAW_EXTRA_AGENTS_JSON_B64
  Dockerfile->>Dockerfile: docker build (passes base64 ARG)
  Dockerfile->>generateOpenclawConfig: NEMOCLAW_EXTRA_AGENTS_JSON_B64 env var
  generateOpenclawConfig->>generateOpenclawConfig: decode, validate, normalize
  generateOpenclawConfig->>generateOpenclawConfig: buildAgentsList (main + extras)
  generateOpenclawConfig->>OpencloConf: agents.list with main+extras
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested labels

Docker, Sandbox

Suggested reviewers

  • cv

Poem

🐰 A secondary rabbit hops in,
With validated paths and strict discipline,
The main agent keeps its throne secure,
Build-time baking, forever pure! 🏗️

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature: adding support for baking secondary OpenClaw agents via the NEMOCLAW_EXTRA_AGENTS_JSON environment variable.
Linked Issues check ✅ Passed All code changes directly implement the requirements from #4560 and #4562: validation of extra agents, base64 encoding, Dockerfile configuration, agents.list composition with canonical main first, path containment, field allowlists, and comprehensive test coverage.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing NEMOCLAW_EXTRA_AGENTS_JSON support: Dockerfile, generator script, patching logic, documentation, and corresponding test files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sdang/reopen-4653-extra-agents

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

@sandl99 sandl99 closed this Jun 2, 2026
@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: cloud-onboard-e2e, openclaw-onboard-security-posture-e2e, runtime-overrides-e2e
Optional E2E: rebuild-openclaw-e2e, sandbox-operations-e2e, inference-routing-e2e

Dispatch hint: cloud-onboard-e2e,openclaw-onboard-security-posture-e2e,runtime-overrides-e2e

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • cloud-onboard-e2e (high): Required because the PR changes onboard-time Dockerfile patching and build-time OpenClaw config generation. This job runs the non-interactive installer/onboard path from the target ref, builds the sandbox image, verifies sandbox health, checks inference.local, and exercises security checks against the resulting live sandbox.
  • openclaw-onboard-security-posture-e2e (high): Required because the PR changes OpenClaw agent list generation and validates security-sensitive workspace/agentDir constraints. This job runs a full OpenClaw onboard on a non-root host posture and performs live OpenClaw assistant inference through the canonical main agent, which is the most direct existing guard against accidentally breaking default-agent selection or sandbox security posture.
  • runtime-overrides-e2e (medium): Required as a focused real Dockerfile/config smoke: it builds the production OpenClaw image, reads the generated /sandbox/.openclaw/openclaw.json, and validates the config hash and config mutation behavior. This should catch Dockerfile ARG/ENV or generate-openclaw-config regressions before merge.

Optional E2E

  • rebuild-openclaw-e2e (high): Useful adjacent confidence because rebuild regenerates/replaces OpenClaw sandbox images while preserving state and config. The new agents.list shape could interact with rebuild config preservation, but the PR does not directly change rebuild logic.
  • sandbox-operations-e2e (high): Useful adjacent confidence for the real user flow after onboarding: list/status/logs/exec plus an OpenClaw agent turn through the main agent. Optional because openclaw-onboard-security-posture-e2e already exercises the main assistant path.
  • inference-routing-e2e (medium): Optional confidence for inference.local routing and credential isolation after the OpenClaw config generator changes. The PR does not directly modify provider routing, so this is adjacent rather than merge-blocking.

New E2E recommendations

  • Extra OpenClaw agents (high): No existing E2E appears to set NEMOCLAW_EXTRA_AGENTS_JSON during onboard. Add a focused live E2E that onboards with a valid secondary agent, verifies openclaw.json has main first/default plus the extra agent with canonical workspace and agentDir paths, verifies the workspace is provisioned with safe ownership, invokes both main and the secondary agent if supported, and confirms malformed extra-agent JSON fails image build with an actionable validator error.
    • Suggested test: extra-openclaw-agents-onboard-e2e

Dispatch hint

  • Workflow: .github/workflows/nightly-e2e.yaml
  • jobs input: cloud-onboard-e2e,openclaw-onboard-security-posture-e2e,runtime-overrides-e2e

@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

E2E Scenario Advisor Recommendation

Required scenario E2E: ubuntu-repo-cloud-openclaw
Optional scenario E2E: ubuntu-repo-openai-compatible-openclaw, wsl-repo-cloud-openclaw, macos-repo-cloud-openclaw

Dispatch required scenario E2E:

  • gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw

Workflow run

Full scenario advisor summary

E2E Scenario Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required scenario E2E

  • ubuntu-repo-cloud-openclaw: Dockerfile build args/env, OpenClaw config generation, and the host-side onboard Dockerfile patcher changed for OpenClaw agents.list/extra-agent baking. The Ubuntu repo cloud OpenClaw scenario is the primary non-special-runner path that builds from the current branch, runs OpenClaw onboarding, and validates the resulting sandbox/inference/credentials baseline.
    • Dispatch: gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-cloud-openclaw

Optional scenario E2E

  • ubuntu-repo-openai-compatible-openclaw: Optional adjacent OpenClaw provider path: the config-generation change is provider-independent, and this checks that OpenAI-compatible onboarding still produces a runnable OpenClaw sandbox after agents.list is always emitted.
    • Dispatch: gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=ubuntu-repo-openai-compatible-openclaw
  • wsl-repo-cloud-openclaw: Optional special-runner adjacent platform coverage for the same repo-current cloud OpenClaw onboarding surface on WSL.
    • Dispatch: gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=wsl-repo-cloud-openclaw
  • macos-repo-cloud-openclaw: Optional special-runner adjacent platform coverage for repo-current cloud OpenClaw CLI/onboarding setup on macOS; Docker-dependent suites are skipped on hosted macOS.
    • Dispatch: gh workflow run e2e-scenarios.yaml --ref <pr-head-ref> --field scenarios=macos-repo-cloud-openclaw

Relevant changed files

  • Dockerfile
  • scripts/generate-openclaw-config.mts
  • src/lib/onboard/dockerfile-patch.ts

@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor

Findings: 0 needs attention, 4 worth checking, 1 nice ideas
Top item: Prove deny-only secondary-agent tool policies do not over-grant tools

Review findings

🛠️ Needs attention

  • None.

🔎 Worth checking

  • Source-of-truth review needed: OpenClaw default-agent resolver compatibility: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: `test/generate-openclaw-config.test.ts` comments state the authoritative resolver lives in the OpenClaw npm package; the test locally computes `find(default) ?? list[0]`.
  • Source-of-truth review needed: OpenClaw secondary-agent tool-policy semantics: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: `validateExtraAgentTools()` accepts non-empty deny[] without allow[]; docs claim nothing is implicitly granted.
  • Prove deny-only secondary-agent tool policies do not over-grant tools (scripts/generate-openclaw-config.mts:523): The validator accepts a secondary agent when either tools.allow[] or tools.deny[] is non-empty, and the docs state that nothing is implicitly granted. That promise depends on OpenClaw's effective policy semantics. If OpenClaw interprets a deny-only policy as 'all tools except these denied', an operator could accidentally bake a secondary agent with broader tool access than intended.
    • Recommendation: Either require a non-empty allow[] for every secondary agent, or add a contract/runtime test against the pinned OpenClaw version showing that deny-only entries remain deny-by-default and cannot access tools outside the intended policy.
    • Evidence: validateExtraAgentTools() computes hasAllow/hasDeny and accepts !hasAllow && hasDeny; docs/reference/commands.mdx says '`tools` must declare a non-empty `allow[]` or `deny[]`; nothing is implicitly granted.' Tests validate JSON shape and rejection paths, but do not exercise effective OpenClaw authorization behavior.
  • OpenClaw default-agent resolver contract is simulated locally rather than validated against OpenClaw (test/generate-openclaw-config.test.ts:1229): The PR correctly bakes `{ id: "main", default: true }` first, but the regression for OpenClaw's `resolveDefaultAgentId` behavior is a local simulation of the upstream fallback contract. If the pinned OpenClaw resolver changes shape, this test could keep passing while the runtime behavior drifts.
    • Recommendation: Add or identify a targeted integration/contract validation that loads the generated config through the pinned OpenClaw agent resolution path, or otherwise assert the upstream resolver contract from the installed OpenClaw package.
    • Evidence: The test named "matches OpenClaw's resolveDefaultAgentId fallback shape for the baked list" reimplements `list.find(default) ?? list[0]` locally; comments note the authoritative resolver lives in the OpenClaw npm package.

🌱 Nice ideas

Workflow run details

This is an automated advisory review. A human maintainer must make the final merge decision.

@sandl99
sandl99 deleted the sdang/reopen-4653-extra-agents branch June 2, 2026 14:20
@wscurran wscurran added feature PR adds or expands user-visible functionality and removed enhancement: feature labels Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature PR adds or expands user-visible functionality integration: openclaw OpenClaw integration behavior

Projects

None yet

3 participants