openclaw - ✅(Solved) Fix [Bug]: Plugin tools loaded in chat/agent execution do not inherit gateway subagent runtime/scope, causing delegated plugin tools like lcm_expand_query to fail [4 pull requests, 7 comments, 4 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#50131Fetched 2026-04-08 00:58:49
View on GitHub
Comments
7
Participants
4
Timeline
18
Reactions
0
Timeline (top)
commented ×7cross-referenced ×3labeled ×2mentioned ×2

When a plugin tool depends on runtime.subagent.* methods, it can fail during normal chat/agent execution even though:

the plugin is installed and loaded, the tool is visible in the tool surface, simpler plugin tools from the same plugin work, and gateway-side plugin runtime support for subagent delegation exists. This appears to happen because the chat/agent-side plugin tool loading/execution path re-loads plugin tools without passing runtimeOptions.subagent, and also does not appear to execute plugin tools inside withPluginRuntimeGatewayRequestScope(...).

As a result, plugin tools that require delegated subagent execution receive the default unavailable stub:

Plugin runtime subagent methods are only available during a gateway request.

Concrete example Using @martian-engineering/lossless-claw:

lcm_grep ✅ works lcm_describe ✅ works lcm_expand_query ❌ visible but fails at execution time with: Plugin runtime subagent methods are only available during a gateway request.

This strongly suggests the problem is not tool registration or exposure anymore, but runtime injection during execution.

Error Message

lcm_expand_query(...) → fails with gateway-request/subagent-runtime error throw new Error("Plugin runtime subagent methods are only available during a gateway request.");

Root Cause

the plugin is installed and loaded, the tool is visible in the tool surface, simpler plugin tools from the same plugin work, and gateway-side plugin runtime support for subagent delegation exists. This appears to happen because the chat/agent-side plugin tool loading/execution path re-loads plugin tools without passing runtimeOptions.subagent, and also does not appear to execute plugin tools inside withPluginRuntimeGatewayRequestScope(...).

Fix Action

Fix / Workaround

and createGatewaySubagentRuntime() dispatches real gateway methods like: agent agent.wait sessions.get sessions.delete

Any plugin tool that depends on: delegated subagents runtime subagent APIs request-scoped gateway dispatch

PR fix notes

PR #1: fix: plugin tools inherit gateway subagent runtime in chat execution

Description (problem / solution / changelog)

Summary

  • ensure plugin tool execution inherits the gateway subagent runtime in chat execution paths
  • align the plugin tool path with the expected runtime selection behavior

Testing

  • tests previously passed locally during fix validation

Closes #50131

Changed files

  • src/gateway/server-methods/agent.test.ts (modified, +51/-0)
  • src/gateway/server-methods/agent.ts (modified, +13/-1)

PR #51141: fix: plugin tools inherit gateway subagent runtime in chat execution

Description (problem / solution / changelog)

Summary

  • ensure plugin tool execution inherits the gateway subagent runtime in chat execution paths
  • align the plugin tool path with the expected runtime selection behavior

Testing

  • tests previously passed locally during fix validation

Closes #50131

Changed files

  • src/gateway/server-methods/agent.test.ts (modified, +51/-0)
  • src/gateway/server-methods/agent.ts (modified, +13/-1)

PR #59396: Propagate gateway subagent binding through embedded runs

Description (problem / solution / changelog)

Propagate gateway subagent binding through embedded runs

Summary

Describe the problem and fix in 2–5 bullets:

If this PR fixes a plugin beta-release blocker, title it fix(<plugin-id>): beta blocker - <summary> and link the matching Beta blocker: <plugin-name> - <summary> issue labeled beta-blocker. Contributors cannot label PRs, so the title is the PR-side signal for maintainers and automation.

  • Problem: Some plugin-backed workflows can still fail with Plugin runtime subagent methods are only available during a gateway request. because several embedded execution paths call runEmbeddedPiAgent(...) without explicitly preserving gateway subagent binding.
  • Why it matters: In real usage this breaks gateway-triggered plugin workflows after the command has already started, so the failure shows up deep in runtime execution instead of at the plugin boundary.
  • What changed: This PR adds allowGatewaySubagentBinding: true to the remaining embedded-agent call sites in command execution, slug generation, and auth probe flows, and adds regression tests that lock that contract in.
  • What did NOT change (scope boundary): This PR does not change plugin logic, workflow logic, queue/retry behavior, or any plugin-specific fallback. It only fixes runtime flag propagation in openclaw.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #50131
  • Related #51141
  • This PR fixes a bug or regression

Root Cause / Regression History (if applicable)

For bug fixes or regressions, explain why this happened, not just what changed. Otherwise write N/A. If the cause is unclear, write Unknown.

  • Root cause: Several production call sites still invoked runEmbeddedPiAgent(...) without allowGatewaySubagentBinding: true, so runtime plugin loading could fall back to the unavailable subagent stub even when the original action came from a gateway request.
  • Missing detection / guardrail: There were no focused tests asserting that these embedded execution paths preserve gateway subagent binding.
  • Prior context (git blame, prior PR, issue, or refactor if known): Related runtime binding discussion exists in #50131, and the tool-loading side was partially addressed in #51141, but these remaining execution call sites were still unpatched.
  • Why this regressed now: The runtime behavior became more visible as plugin workflows increasingly rely on runtime.subagent, while these older embedded run paths still assumed binding would be implicit.
  • If unknown, what was ruled out: Plugin-side business logic and workflow-level queue/replay logic were ruled out; the failing condition comes from core runtime binding, not plugin logic.

Regression Test Plan (if applicable)

For bug fixes or regressions, name the smallest reliable test coverage that should have caught this. Otherwise write N/A.

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file:
    • src/commands/agent.test.ts
    • src/hooks/llm-slug-generator.test.ts
    • src/commands/models/list.probe.runtime.test.ts
  • Scenario the test should lock in: Embedded command execution, slug generation, and auth probe paths must pass allowGatewaySubagentBinding: true to runEmbeddedPiAgent(...).
  • Why this is the smallest reliable guardrail: The bug is a runtime flag propagation gap at specific call sites, so focused unit tests on those call boundaries are the narrowest tests that directly prevent regression.
  • Existing test that already covers this (if any): src/commands/agent.test.ts already covered command execution broadly; this PR extends it to assert the runtime flag.
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

List user-visible changes (including defaults/config).
If none, write None.

  • Gateway-triggered plugin workflows are less likely to fail with Plugin runtime subagent methods are only available during a gateway request. when execution passes through embedded command runs.
  • Internal auth probe and LLM slug generation flows now preserve the same runtime binding contract as the main gateway command path.

Diagram (if applicable)

For UI changes or non-trivial logic flows, include a small ASCII diagram reviewers can scan quickly. Otherwise write N/A.

Before:
[gateway request] -> [embedded run without explicit binding] -> [plugin runtime gets unavailable subagent stub] -> [runtime error]

After:
[gateway request] -> [embedded run with allowGatewaySubagentBinding=true] -> [plugin runtime keeps gateway-bound subagent] -> [workflow continues]

Security Impact (required)

  • New permissions/capabilities? (Yes/No) No
  • Secrets/tokens handling changed? (Yes/No) No
  • New/changed network calls? (Yes/No) No
  • Command/tool execution surface changed? (Yes/No) No
  • Data access scope changed? (Yes/No) No
  • If any Yes, explain risk + mitigation: N/A

Repro + Verification

Environment

  • OS: macOS
  • Runtime/container: local openclaw development checkout
  • Model/provider: provider-agnostic; exercised via mocked embedded Pi agent calls
  • Integration/channel (if any): gateway-triggered plugin workflows, including Discord-style command execution paths
  • Relevant config (redacted): default gateway/plugin runtime configuration where plugin workflows can call runtime.subagent

Steps

  1. Trigger a gateway-backed plugin workflow that eventually executes through an embedded-agent path.
  2. Let the command reach a code path such as normal command execution, LLM slug generation, or auth probing.
  3. Observe whether plugin runtime subagent access is preserved.

Expected

  • Embedded runs preserve gateway subagent binding and plugin runtime can access runtime.subagent without raising the gateway-request error.

Actual

  • Before this fix, some embedded paths could still lose the binding and fail with Plugin runtime subagent methods are only available during a gateway request.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: Ran targeted Vitest coverage for the three affected execution paths and confirmed all of them now pass with the explicit runtime flag in place.
  • Edge cases checked: Normal command execution, ingress command path, one-off slug generation, and auth probe execution all preserve allowGatewaySubagentBinding.
  • What you did not verify: I did not run a full live Discord end-to-end reproduction against a production gateway in this PR branch.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

Compatibility / Migration

  • Backward compatible? (Yes/No) Yes
  • Config/env changes? (Yes/No) No
  • Migration needed? (Yes/No) No
  • If yes, exact upgrade steps: N/A

Risks and Mitigations

List only real risks for this PR. Add/remove entries as needed. If none, write None.

  • Risk:
    • A future embedded execution path could be added without the same runtime flag and reintroduce the bug.
    • Mitigation:
      • This PR adds focused regression tests around the known production call sites so similar omissions are easier to catch during review and CI.

Changed files

  • src/agents/command/attempt-execution.ts (modified, +1/-0)
  • src/commands/agent.test.ts (modified, +8/-0)
  • src/commands/models/list.probe.runtime.test.ts (added, +63/-0)
  • src/commands/models/list.probe.ts (modified, +1/-0)
  • src/hooks/llm-slug-generator.test.ts (added, +49/-0)
  • src/hooks/llm-slug-generator.ts (modified, +1/-0)

PR #62870: fix(agents): preserve plugin tools in subagent scopes

Description (problem / solution / changelog)

Summary

  • Adds preservePluginTools parameter to buildDefaultToolPolicyPipelineSteps()
  • When resolving tools for subagent sessions, agent/group policy steps no longer strip plugin-only tools
  • resolveGatewayScopedTools() passes preservePluginTools: true when isSubagentSessionKey() is true

Problem

buildDefaultToolPolicyPipelineSteps() hardcodes stripPluginOnlyAllowlist: true for all 7 pipeline steps. When the pipeline runs for a subagent session, plugin tools are stripped in steps 1-7 before the subagent policy step (step 8) can include them. The subagent inherits an empty plugin tool set regardless of its config.

Root Cause

The security change in v2026.3.11 was too aggressive — stripPluginOnlyAllowlist should be false for agent-specific and group policy steps when resolving tools for subagent scopes.

Files Changed

  • src/agents/tool-policy-pipeline.ts — new preservePluginTools param, conditional flag on agent/group steps
  • src/gateway/tool-resolution.ts — passes preservePluginTools: true for subagent sessions

Test plan

  • Existing tool-policy-pipeline.test.ts tests pass
  • Subagent sessions inherit plugin tools when parent config includes group:plugins
  • Non-subagent sessions still strip plugin-only allowlists (no regression)

Fixes #50131

Created by Claude Code on behalf of @kvttvrsis

Changed files

  • src/agents/tool-policy-pipeline.ts (modified, +14/-3)
  • src/gateway/tool-resolution.ts (modified, +4/-0)

Code Example

Evidence / code path notes
1) Default plugin runtime falls back to unavailable subagent stub
In plugin runtime creation:

function createPluginRuntime(_options = {}) {
return {
...
subagent: _options.subagent ?? createUnavailableSubagentRuntime(),
...
};
}


and the unavailable runtime throws:

throw new Error("Plugin runtime subagent methods are only available during a gateway request.");


2) Gateway path does have real subagent runtime
Gateway plugin loading uses:

loadOpenClawPlugins({
...
runtimeOptions: { subagent: createGatewaySubagentRuntime() }
})


and createGatewaySubagentRuntime() dispatches real gateway methods like:
agent
agent.wait
sessions.get
sessions.delete

3) Gateway request scope exists and is wired
Gateway request handling wraps execution in:

withPluginRuntimeGatewayRequestScope({
context,
client,
isWebchatConnect
}, invokeHandler)


So the gateway-side machinery for scoped plugin runtime access is already present.

4) Chat/agent plugin tool loading appears to re-load plugins without runtimeOptions
On the agent/chat side, plugin tools are collected via something like:

const pluginTools = resolvePluginTools({
context: { ... },
existingToolNames: ...,
toolAllowlist: ...
});


Inside resolvePluginTools(...), plugins are loaded again via:

loadOpenClawPlugins({
config: effectiveConfig,
workspaceDir: params.context.workspaceDir,
env,
logger: ...
});


There is no visible runtimeOptions.subagent passed there.
5) Chat/agent-side execution path does not appear to wrap plugin tool execution in gateway request scope
In the chat/agent execution bundle, we found wrappers like:
parameter normalization
abort-signal wrapping
before-tool-call hook wrapping

But did not find evidence of:
withPluginRuntimeGatewayRequestScope(...)
handleGatewayRequest(...)

So it looks like plugin tools are executed outside the gateway-scoped runtime context.

---

Likely root cause
There seem to be two different plugin-runtime environments:
Gateway plugin runtime
has runtimeOptions.subagent
has request-scoped gateway context
supports delegated plugin tools

Chat/agent plugin tool runtime
can expose/load plugin tools
but appears to omit runtimeOptions.subagent
and appears not to establish plugin gateway request scope

That mismatch causes plugin tools that rely on runtime.subagent.* to be partially functional:
visible
callable
but broken at runtime

---
Suggested fixes
Option APreferred
When plugin tools are resolved/loaded for chat/agent execution, ensure they receive a gateway-backed runtime, including:

runtimeOptions.subagent: createGatewaySubagentRuntime()
request-scope setup equivalent to gateway request execution

That would make plugin tools behave consistently between:
gateway/plugin handler contexts
normal agent/chat tool execution

Option B
If that runtime cannot be safely provided in chat/agent execution, then tools that depend on runtime.subagent.* should not be surfaced as normal chat tools unless the required runtime contract is available.

In other words:
fail early and explicitly
not deep inside tool.execute()

Option C
Add an execution wrapper for plugin tools so they run under:

withPluginRuntimeGatewayRequestScope(...)


with appropriate request context when invoked from normal agent execution.

---

Why this matters
This is not specific to lossless-claw.

Any plugin tool that depends on:
delegated subagents
runtime subagent APIs
request-scoped gateway dispatch

can become “half-working”:
discoverable
exposed
but failing only when it reaches the deeper runtime path

That makes plugin tool behavior inconsistent and hard to debug.

---
RAW_BUFFERClick to expand / collapse

Bug type

Regression (worked before, now fails)

Summary

When a plugin tool depends on runtime.subagent.* methods, it can fail during normal chat/agent execution even though:

the plugin is installed and loaded, the tool is visible in the tool surface, simpler plugin tools from the same plugin work, and gateway-side plugin runtime support for subagent delegation exists. This appears to happen because the chat/agent-side plugin tool loading/execution path re-loads plugin tools without passing runtimeOptions.subagent, and also does not appear to execute plugin tools inside withPluginRuntimeGatewayRequestScope(...).

As a result, plugin tools that require delegated subagent execution receive the default unavailable stub:

Plugin runtime subagent methods are only available during a gateway request.

Concrete example Using @martian-engineering/lossless-claw:

lcm_grep ✅ works lcm_describe ✅ works lcm_expand_query ❌ visible but fails at execution time with: Plugin runtime subagent methods are only available during a gateway request.

This strongly suggests the problem is not tool registration or exposure anymore, but runtime injection during execution.

Steps to reproduce

Install and enable lossless-claw Ensure plugin tools are visible in chat/agent tool surface Call: lcm_grep → works lcm_describe → works lcm_expand_query(...) → fails with gateway-request/subagent-runtime error

In our case, plugin visibility first required fixing provider tool policy: tools.byProvider.rawchat.profile had been "coding" changing it to "full" restored lcm_* visibility

After that: visibility was fixed lcm_expand_query still failed due to runtime/subagent context

Expected behavior

If a plugin tool is available in normal chat/agent execution, and that tool relies on runtime.subagent.*, it should either:

receive a live gateway-backed subagent runtime and request scope, or be explicitly rejected at registration/exposure time if the runtime contract cannot be met

What should not happen is: tool is visible, tool can be called, but it receives a stub runtime that only fails at deep execution time.

Actual behavior

The plugin tool is visible and callable, but delegated execution fails with: Plugin runtime subagent methods are only available during a gateway request.


OpenClaw version

2026.3.13

Operating system

Ubuntu 25.10

Install method

No response

Model

gpt 5.4

Provider / routing chain

openclaw -> openai -> gpt5.4

Config file / key location

No response

Additional provider/model setup details

No response

Logs, screenshots, and evidence

Evidence / code path notes
1) Default plugin runtime falls back to unavailable subagent stub
In plugin runtime creation:

function createPluginRuntime(_options = {}) {
return {
...
subagent: _options.subagent ?? createUnavailableSubagentRuntime(),
...
};
}


and the unavailable runtime throws:

throw new Error("Plugin runtime subagent methods are only available during a gateway request.");


2) Gateway path does have real subagent runtime
Gateway plugin loading uses:

loadOpenClawPlugins({
...
runtimeOptions: { subagent: createGatewaySubagentRuntime() }
})


and createGatewaySubagentRuntime() dispatches real gateway methods like:
agent
agent.wait
sessions.get
sessions.delete

3) Gateway request scope exists and is wired
Gateway request handling wraps execution in:

withPluginRuntimeGatewayRequestScope({
context,
client,
isWebchatConnect
}, invokeHandler)


So the gateway-side machinery for scoped plugin runtime access is already present.

4) Chat/agent plugin tool loading appears to re-load plugins without runtimeOptions
On the agent/chat side, plugin tools are collected via something like:

const pluginTools = resolvePluginTools({
context: { ... },
existingToolNames: ...,
toolAllowlist: ...
});


Inside resolvePluginTools(...), plugins are loaded again via:

loadOpenClawPlugins({
config: effectiveConfig,
workspaceDir: params.context.workspaceDir,
env,
logger: ...
});


There is no visible runtimeOptions.subagent passed there.
5) Chat/agent-side execution path does not appear to wrap plugin tool execution in gateway request scope
In the chat/agent execution bundle, we found wrappers like:
parameter normalization
abort-signal wrapping
before-tool-call hook wrapping

But did not find evidence of:
withPluginRuntimeGatewayRequestScope(...)
handleGatewayRequest(...)

So it looks like plugin tools are executed outside the gateway-scoped runtime context.

---

Likely root cause
There seem to be two different plugin-runtime environments:
Gateway plugin runtime
has runtimeOptions.subagent
has request-scoped gateway context
supports delegated plugin tools

Chat/agent plugin tool runtime
can expose/load plugin tools
but appears to omit runtimeOptions.subagent
and appears not to establish plugin gateway request scope

That mismatch causes plugin tools that rely on runtime.subagent.* to be partially functional:
visible
callable
but broken at runtime

---
Suggested fixes
Option A — Preferred
When plugin tools are resolved/loaded for chat/agent execution, ensure they receive a gateway-backed runtime, including:

runtimeOptions.subagent: createGatewaySubagentRuntime()
request-scope setup equivalent to gateway request execution

That would make plugin tools behave consistently between:
gateway/plugin handler contexts
normal agent/chat tool execution

Option B
If that runtime cannot be safely provided in chat/agent execution, then tools that depend on runtime.subagent.* should not be surfaced as normal chat tools unless the required runtime contract is available.

In other words:
fail early and explicitly
not deep inside tool.execute()

Option C
Add an execution wrapper for plugin tools so they run under:

withPluginRuntimeGatewayRequestScope(...)


with appropriate request context when invoked from normal agent execution.

---

Why this matters
This is not specific to lossless-claw.

Any plugin tool that depends on:
delegated subagents
runtime subagent APIs
request-scoped gateway dispatch

can become “half-working”:
discoverable
exposed
but failing only when it reaches the deeper runtime path

That makes plugin tool behavior inconsistent and hard to debug.

---

Impact and severity

No response

Additional information

No response

extent analysis

Fix Plan

To resolve the issue, we will implement Option A — Preferred. This involves ensuring that plugin tools receive a gateway-backed runtime when loaded for chat/agent execution.

Step-by-Step Solution

  1. Modify the resolvePluginTools function to pass runtimeOptions.subagent when loading plugins:

const pluginTools = resolvePluginTools({ context: { ... }, existingToolNames: ..., toolAllowlist: ..., runtimeOptions: { subagent: createGatewaySubagentRuntime() } });

2. **Update the `loadOpenClawPlugins` function** to accept and use `runtimeOptions.subagent`:
   ```javascript
loadOpenClawPlugins({
  config: effectiveConfig,
  workspaceDir: params.context.workspaceDir,
  env,
  logger: ...,
  runtimeOptions: {
    subagent: createGatewaySubagentRuntime()
  }
});
  1. Wrap plugin tool execution in withPluginRuntimeGatewayRequestScope to establish the request-scoped gateway context:

withPluginRuntimeGatewayRequestScope({ context, client, isWebchatConnect }, () => { // Execute plugin tool here });


### Verification
To verify that the fix worked:
1. Install and enable the `lossless-claw` plugin.
2. Ensure plugin tools are visible in the chat/agent tool surface.
3. Call `lcm_grep`, `lcm_describe`, and `lcm_expand_query` to test their functionality.
4. Verify that `lcm_expand_query` no longer fails with the "Plugin runtime subagent methods are only available during a gateway request" error.

### Extra Tips
* Ensure that the `createGatewaySubagentRuntime` function is correctly implemented to provide the necessary subagent runtime.
* Test the fix with different plugin tools that rely on `runtime.subagent.*` to ensure consistency.
* Consider implementing **Option B** as a fallback to explicitly reject tools that cannot be provided with the required runtime contract.

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…

FAQ

Expected behavior

If a plugin tool is available in normal chat/agent execution, and that tool relies on runtime.subagent.*, it should either:

receive a live gateway-backed subagent runtime and request scope, or be explicitly rejected at registration/exposure time if the runtime contract cannot be met

What should not happen is: tool is visible, tool can be called, but it receives a stub runtime that only fails at deep execution time.

Still need to ship something?

×6

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

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Bug]: Plugin tools loaded in chat/agent execution do not inherit gateway subagent runtime/scope, causing delegated plugin tools like lcm_expand_query to fail [4 pull requests, 7 comments, 4 participants]