openclaw - 💡(How to fix) Fix [Bug]: tools: [] in createAgentSession disables all tools including customTools after pi 0.68.1 upgrade [2 comments, 3 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#69974Fetched 2026-04-23 07:30:49
View on GitHub
Comments
2
Participants
3
Timeline
4
Reactions
0
Author
Timeline (top)
commented ×2closed ×1labeled ×1

After upgrading @mariozechner/pi-* packages from 0.67.68 to 0.68.1 (commit 0f4dc42767), all tool calls are silently disabled. The LLM API request body contains no tools field, so the model responds text-only and never invokes any tools (read, write, edit, exec, web_search, etc.).

Error Message

  • All tools silently disabled — no error logged, no warning Critical — all tool calls silently disabled for all models, all providers, all channels. No error or warning emitted. Affects every user on version 2026.4.22.

Root Cause

pi-coding-agent 0.68.1 changed createAgentSession({ tools }) from a built-in tool object list (AgentTool[]) to a tool-name allowlist (string[]). OpenClaw's splitSdkTools() always returns builtInTools: [] and passes all tools via customTools. In 0.68.1, the empty array [] is truthy, causing new Set([]) to be created as the allowlist — which rejects every tool name, including those in customTools.

// pi-coding-agent 0.68.1 — agent-session.js:128
this._allowedToolNames = config.allowedToolNames
  ? new Set(config.allowedToolNames)  // new Set([]) — truthy, empty set
  : undefined;

// line 1787
const isAllowedTool = (name) => !allowedToolNames || allowedToolNames.has(name);
// → !Set() || Set().has("read") → false || false → false
// ALL tools filtered out

Code Example

// pi-coding-agent 0.68.1 — agent-session.js:128
this._allowedToolNames = config.allowedToolNames
  ? new Set(config.allowedToolNames)  // new Set([]) — truthy, empty set
  : undefined;

// line 1787
const isAllowedTool = (name) => !allowedToolNames || allowedToolNames.has(name);
// → !Set() || Set().has("read") → false || false → false
// ALL tools filtered out

---

--- a/src/agents/pi-embedded-runner/tool-split.ts
+++ b/src/agents/pi-embedded-runner/tool-split.ts
 export function splitSdkTools(options: { tools: AnyAgentTool[]; sandboxEnabled: boolean }): {
-  builtInTools: string[];
+  builtInTools: string[] | undefined;
   customTools: ReturnType<typeof toToolDefinitions>;
 } {
   const { tools } = options;
   return {
-    builtInTools: [],
+    builtInTools: undefined,
     customTools: toToolDefinitions(tools),
   };
 }

---

// agent-session.js:128
this._allowedToolNames = config.allowedToolNames?.length
  ? new Set(config.allowedToolNames)
  : undefined;
RAW_BUFFERClick to expand / collapse

Beta blocker: openclaw — createAgentSession({ tools: [] }) silently disables all tools in pi 0.68.1

Bug type

Regression (worked before, now fails)

Beta release blocker

Yes

Summary

After upgrading @mariozechner/pi-* packages from 0.67.68 to 0.68.1 (commit 0f4dc42767), all tool calls are silently disabled. The LLM API request body contains no tools field, so the model responds text-only and never invokes any tools (read, write, edit, exec, web_search, etc.).

Root cause

pi-coding-agent 0.68.1 changed createAgentSession({ tools }) from a built-in tool object list (AgentTool[]) to a tool-name allowlist (string[]). OpenClaw's splitSdkTools() always returns builtInTools: [] and passes all tools via customTools. In 0.68.1, the empty array [] is truthy, causing new Set([]) to be created as the allowlist — which rejects every tool name, including those in customTools.

// pi-coding-agent 0.68.1 — agent-session.js:128
this._allowedToolNames = config.allowedToolNames
  ? new Set(config.allowedToolNames)  // new Set([]) — truthy, empty set
  : undefined;

// line 1787
const isAllowedTool = (name) => !allowedToolNames || allowedToolNames.has(name);
// → !Set() || Set().has("read") → false || false → false
// ALL tools filtered out

Steps to reproduce

  1. Install openclaw at version 2026.4.22 (includes pi packages 0.68.1)
  2. Start any agent session via any channel (QQ Bot, CLI, gateway, etc.)
  3. Send a message that would normally trigger tool use, e.g. "list files in current directory" or "read file X"
  4. Observe: model responds with plain text describing what it would do, but never actually calls any tool

Expected behavior

Tools are injected into the API request. The model calls tools (read, exec, write, etc.) as needed.

Actual behavior

  • The API request body has no tools field
  • Model responds text-only, e.g. outputs <exec command="ls"> as literal text instead of calling the exec tool
  • All tools silently disabled — no error logged, no warning

Evidence

Screenshot

Model outputs tool XML as text instead of executing:

Image

Code trace

  1. splitSdkTools() returns builtInTools: [] → passed to createAgentSession({ tools: [] })
  2. SDK creates allowedToolNames = new Set([]) (truthy, empty)
  3. isAllowedTool(name) returns false for all tools
  4. context.tools is empty when reaching buildOpenAICompletionsParams()
  5. if (context.tools) branch is skipped → no tools in request body

Rollback verification

Rolling back to pi-* 0.67.68 restores tool functionality.

Environment

ItemValue
OpenClaw version2026.4.22
OSmacOS (reproducible on all platforms)
Install methodpnpm
ModelAll models affected
Provideropenai-completions, openai-responses, anthropic-messages — all share the same createAgentSession path

Introduced by

Commit 0f4dc42767build: update pi packages to 0.68.1

Changed files:

  • package.json: @mariozechner/pi-* 0.67.68 → 0.68.1
  • src/agents/pi-tools.ts: codingToolscreateCodingTools()
  • src/agents/pi-embedded-runner/tool-split.ts: builtInTools: AnyAgentTool[]string[]

Suggested fix

Option A — OpenClaw side (1 file, 3 lines)

--- a/src/agents/pi-embedded-runner/tool-split.ts
+++ b/src/agents/pi-embedded-runner/tool-split.ts
 export function splitSdkTools(options: { tools: AnyAgentTool[]; sandboxEnabled: boolean }): {
-  builtInTools: string[];
+  builtInTools: string[] | undefined;
   customTools: ReturnType<typeof toToolDefinitions>;
 } {
   const { tools } = options;
   return {
-    builtInTools: [],
+    builtInTools: undefined,
     customTools: toToolDefinitions(tools),
   };
 }

Option B — SDK side (pi-coding-agent)

// agent-session.js:128
this._allowedToolNames = config.allowedToolNames?.length
  ? new Set(config.allowedToolNames)
  : undefined;

Impact and severity

Critical — all tool calls silently disabled for all models, all providers, all channels. No error or warning emitted. Affects every user on version 2026.4.22.

Scope

NOT_ENOUGH_INFO on whether other consumers of createAgentSession are affected — only the embedded runner path (attempt.ts) was traced.

extent analysis

TL;DR

The most likely fix is to update the splitSdkTools function in OpenClaw to return builtInTools as undefined instead of an empty array, or update the pi-coding-agent to check for the length of allowedToolNames before creating a new Set.

Guidance

  • Verify that the issue is caused by the change in createAgentSession from AgentTool[] to string[] by checking the allowedToolNames variable in the agent-session.js file.
  • Apply the suggested fix from Option A by updating the splitSdkTools function to return builtInTools as undefined when the input array is empty.
  • Alternatively, apply the suggested fix from Option B by updating the pi-coding-agent to check for the length of allowedToolNames before creating a new Set.
  • Test the fix by sending a message that would normally trigger tool use and verifying that the model calls the tools as expected.

Example

// Updated splitSdkTools function
export function splitSdkTools(options: { tools: AnyAgentTool[]; sandboxEnabled: boolean }): {
  builtInTools: string[] | undefined;
  customTools: ReturnType<typeof toToolDefinitions>;
} {
  const { tools } = options;
  return {
    builtInTools: tools.length > 0 ? [] : undefined,
    customTools: toToolDefinitions(tools),
  };
}

Notes

The suggested fixes assume that the issue is caused by the change in createAgentSession and that the splitSdkTools function is the root cause of the problem. However, without more information about the pi-coding-agent and its dependencies, it is difficult to determine the full scope of the issue.

Recommendation

Apply the fix from Option A, which updates the splitSdkTools function to return builtInTools as undefined when the input array is empty. This fix is more straightforward and less likely to introduce new issues.

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

Tools are injected into the API request. The model calls tools (read, exec, write, etc.) as needed.

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 - 💡(How to fix) Fix [Bug]: tools: [] in createAgentSession disables all tools including customTools after pi 0.68.1 upgrade [2 comments, 3 participants]