Skip to main content

M10 - OpenClaw Concrete Executor, Agent-Node Pilot, and Safety Gates

Status: delivered.

M9 proved the orchestration-runtime seam and piloted one read-only node (track_progress) through a fake executor. M10 (issues #82- #88) replaces the fake executor with a real, gateway-backed one; extends the pilot to one state-only agent node; adds a centralized, code-owned capability policy so config alone can never widen what OpenClaw may execute; and adds the machine-checkable flip-readiness gate operators run before switching a real environment onto the pilot.

Result

  • Concrete executor (M10-1..M10-4, issues #82-#85): OpenClawGatewayNodeExecutor and OpenClawExecutorGatewayClient (bloom/workflow/openclaw_executor.py) implement the pilot's POST /tools/invoke contract against a real OpenClaw Gateway. create_app wires the concrete executor whenever BLOOM_OPENCLAW_ORCHESTRATION_EXECUTOR_BASE_URL is configured, falling back to UnavailableOpenClawNodeExecutor otherwise; Settings fails fast if fail_closed is selected without that config. An integration harness (bloom/workflow/openclaw_track_progress_harness.py) proves track_progress end to end through the real code path - request shape, idempotency/cached-success reuse, validated writes, and Bloom's own reducer application - offline by default, with an opt-in live-gateway check.
  • Second pilot node (M10-5, issue #86): prd_authoring, a state-only agent node that writes only prd and never messages the user directly, routed through a separate, empty-by-default BLOOM_OPENCLAW_ORCHESTRATION_PILOT_AGENT_NODES allowlist. Explicit by node id, never inferred from node.type == "agent" alone.
  • Capability policy and safety gates (M10-6, issue #87): OpenClawCapabilityPolicy (bloom/workflow/openclaw_policy.py) is a third, code-owned gate above the operator-configured allowlists and below the executor's own tool/agent maps. It rejects any node that is not a tool/agent node, is side-effecting (Telegram sends, GitHub mutations, deploy/CI triggers, PR review publication, merge decisions), falls outside its own hard-coded node set, or declares writes outside what that node id is allowed to write. Policy rejection follows the same fallback/fail-closed semantics as an executor failure and is always logged (openclaw_policy.rejected), never silent. /health's orchestration.policy field exposes a secret-safe summary.
  • Flip-readiness command and runbook (M10-7, issue #88, this milestone's closing issue): bloom.workflow.openclaw_readiness (run via uv run python -m bloom.workflow.openclaw_readiness) is a machine-checkable gate that verifies Settings construction, the configured allowlists against the policy's hard-coded node set, /health, concrete-executor availability, correlation-store health, capability-policy wiring, and an offline run of the track_progress execution harness - entirely in-process, no live OpenClaw gateway required by default - plus an optional, explicitly-marked local-gateway-only live harness check. See docs/deployment.md for the full rollout runbook and docs/design/openclaw-orchestration-runtime.md for the design reference.

Exact M10 Routable Node Set

At the end of M10, exactly these two nodes may ever route through OpenClaw, and only when also present in the operator's configured allowlist:

  • track_progress (tool): read-only GitHub status refresh, writes only progress.
  • prd_authoring (agent): state-only PRD draft, writes only prd.

Every other node in workflows/bloom-sdlc.workflow.json - human, event_wait, map, router, passthrough, and every side-effecting tool node (GitHub mutations, Telegram sends, deploy/CI triggers) - remains built-in-only, enforced by the capability policy regardless of any future config change. Widening this set requires a deliberate, separately-reviewed change to openclaw_policy.py and its tests, never a runtime config value alone.

Retained In Bloom

Unchanged from M9 - Bloom still owns product state and persisted RunState, workflow graph traversal and reducers, GitHub coordination semantics, account/session state, Telegram and GitHub webhook routing, durable job enqueue and event dedupe, GitHub and Telegram side effects, Product Owner review and merge gates, and milestone closure.

Out Of Scope

M10 does not:

  • remove the built-in runtime,
  • route any node beyond track_progress/prd_authoring through OpenClaw,
  • enable any side-effecting node through OpenClaw,
  • move webhook routing, account/product state storage, or business invariants into OpenClaw,
  • automatically flip any real environment's BLOOM_ORCHESTRATION_RUNTIME - the flip-readiness command is a check operators run manually before that decision, not an automated gate.

Not started. The recommended next candidate - noted in Pilot Path Recommendation - is one additional read-only or advisory node (e.g. a status/monitoring answer path, or a pre-publication specialist-review draft), added through the same double-allowlist-plus-capability-policy pattern this milestone established, only after the M10 pilot has run in production behind the flip-readiness check for a full soak period.