openclaw - 💡(How to fix) Fix feat: expose hooks.maxConcurrentRuns config for parallel webhook agent execution [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#55516Fetched 2026-04-08 01:38:38
View on GitHub
Comments
0
Participants
1
Timeline
1
Reactions
4
Participants
Timeline (top)
cross-referenced ×1

Root Cause

dispatchAgentHookrunCronIsolatedAgentTurn(lane: "cron")runEmbeddedPiAgent(lane: resolveNestedAgentLane("cron")) → global lane resolves to "nested".

The "nested" lane is created by getLaneState() with the default maxConcurrent: 1 and is never configured via setCommandLaneConcurrency.

Meanwhile, the "cron", "main", and "subagent" lanes all have config knobs:

// gateway-cli startup
setCommandLaneConcurrency(CommandLane.Cron, cfg.cron?.maxConcurrentRuns ?? 1);
setCommandLaneConcurrency(CommandLane.Main, resolveAgentMaxConcurrent(cfg));
setCommandLaneConcurrency(CommandLane.Subagent, resolveSubagentMaxConcurrent(cfg));
// CommandLane.Nested — not configured, defaults to 1

Fix Action

Fix / Workaround

All hook-dispatched agent runs (action: "agent" in hooks.mappings) serialize on a shared "nested" global lane with maxConcurrent: 1. Even when each webhook event has a unique sessionKey (via transform overrides), only one hook agent can execute at a time — the rest queue behind it.

dispatchAgentHookrunCronIsolatedAgentTurn(lane: "cron")runEmbeddedPiAgent(lane: resolveNestedAgentLane("cron")) → global lane resolves to "nested".

hooks.maxConcurrentRuns:
  type: number
  default: 1
  help: "Maximum number of hook-dispatched agent runs that can execute concurrently on the nested lane."

Code Example

// gateway-cli startup
setCommandLaneConcurrency(CommandLane.Cron, cfg.cron?.maxConcurrentRuns ?? 1);
setCommandLaneConcurrency(CommandLane.Main, resolveAgentMaxConcurrent(cfg));
setCommandLaneConcurrency(CommandLane.Subagent, resolveSubagentMaxConcurrent(cfg));
// CommandLane.Nested — not configured, defaults to 1

---

setCommandLaneConcurrency(CommandLane.Nested, cfg.hooks?.maxConcurrentRuns ?? 1);

---

hooks.maxConcurrentRuns:
  type: number
  default: 1
  help: "Maximum number of hook-dispatched agent runs that can execute concurrently on the nested lane."

---

import { ed as setCommandLaneConcurrency } from "openclaw/dist/pi-embedded-BaSvmUpW.js";
setCommandLaneConcurrency("nested", 3);
RAW_BUFFERClick to expand / collapse

Problem

All hook-dispatched agent runs (action: "agent" in hooks.mappings) serialize on a shared "nested" global lane with maxConcurrent: 1. Even when each webhook event has a unique sessionKey (via transform overrides), only one hook agent can execute at a time — the rest queue behind it.

This is a significant bottleneck for webhook-driven agentic workflows where multiple events (e.g., GitHub project board status changes for different issues) arrive close together. In our case, planning issue A blocks coding issue B blocks reviewing issue C, even though they are completely independent.

Root Cause

dispatchAgentHookrunCronIsolatedAgentTurn(lane: "cron")runEmbeddedPiAgent(lane: resolveNestedAgentLane("cron")) → global lane resolves to "nested".

The "nested" lane is created by getLaneState() with the default maxConcurrent: 1 and is never configured via setCommandLaneConcurrency.

Meanwhile, the "cron", "main", and "subagent" lanes all have config knobs:

// gateway-cli startup
setCommandLaneConcurrency(CommandLane.Cron, cfg.cron?.maxConcurrentRuns ?? 1);
setCommandLaneConcurrency(CommandLane.Main, resolveAgentMaxConcurrent(cfg));
setCommandLaneConcurrency(CommandLane.Subagent, resolveSubagentMaxConcurrent(cfg));
// CommandLane.Nested — not configured, defaults to 1

Proposed Fix

Add a config knob for the nested lane concurrency, following the same pattern as cron.maxConcurrentRuns:

setCommandLaneConcurrency(CommandLane.Nested, cfg.hooks?.maxConcurrentRuns ?? 1);

And add the corresponding schema entry:

hooks.maxConcurrentRuns:
  type: number
  default: 1
  help: "Maximum number of hook-dispatched agent runs that can execute concurrently on the nested lane."

This is a one-line fix in the gateway startup path (plus the schema definition), backward-compatible (defaults to 1), and follows the existing pattern.

Current Workaround

We wrote a custom gateway:startup internal hook that imports setCommandLaneConcurrency from the dist bundle and calls it manually:

import { ed as setCommandLaneConcurrency } from "openclaw/dist/pi-embedded-BaSvmUpW.js";
setCommandLaneConcurrency("nested", 3);

This works but is fragile — the hashed filename and minified export alias change between releases.

Environment

  • OpenClaw 2026.3.24
  • Webhook-driven agentic workflow with 3 hook mappings (planning, coding, review)
  • Dynamic session keys via transform overrides (confirmed working — sessions are separate, but execution still serializes)

Impact

Any user running webhook-driven agent workflows with multiple concurrent events hits this bottleneck. The session-level isolation works correctly, but the global nested lane prevents actual parallel execution.

extent analysis

Fix Plan

To fix the issue, you need to add a configuration option for the nested lane concurrency. Here are the steps:

  • Add the following line to your gateway startup configuration:
setCommandLaneConcurrency(CommandLane.Nested, cfg.hooks?.maxConcurrentRuns ?? 1);
  • Add a schema entry for the hooks.maxConcurrentRuns configuration option:
hooks.maxConcurrentRuns:
  type: number
  default: 1
  help: "Maximum number of hook-dispatched agent runs that can execute concurrently on the nested lane."
  • Update your configuration file to include the hooks.maxConcurrentRuns option, for example:
hooks:
  maxConcurrentRuns: 3

This will allow you to configure the concurrency level for the nested lane.

Verification

To verify that the fix worked, you can test your webhook-driven agentic workflow with multiple concurrent events and check that the agent runs are executing in parallel. You can do this by:

  • Triggering multiple webhook events simultaneously
  • Checking the execution logs to see that multiple agent runs are executing at the same time
  • Verifying that the workflow is completing in a timely manner, without significant delays due to serialization

Extra Tips

  • Make sure to update your configuration file to include the hooks.maxConcurrentRuns option, as this will determine the concurrency level for the nested lane.
  • You can adjust the value of hooks.maxConcurrentRuns to optimize the performance of your workflow, depending on your specific use case and system resources.
  • If you are using a custom gateway:startup internal hook, you can remove it, as the new configuration option makes it unnecessary.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING