[Bug]: A single broken plugin's malformed tool schema crashes every agent run (no per-tool isolation in Anthropic adapter)
Summary
When any loaded plugin registers a tool whose schema is stored under the wrong
key (e.g., inputSchema instead of parameters), the Anthropic tool-conversion
adapter throws TypeError: Cannot read properties of undefined (reading 'properties')
while building the tool list, and every subsequent agent run on any Anthropic
model hits isError=true before the model ever sees the user message.
The error is never surfaced as an informative "plugin X has a broken tool Y" —
the agent just silently fails every turn.
This turns a single broken 3rd-party plugin into a platform-wide hard outage
for Claude users.
Observed in the wild
Plugin: @agntdata/[email protected] (filing a bug report against them
separately — their schema key is inputSchema, OpenClaw's contract is
parameters).
Symptom: every claude-* agent session (main agent, slug generator, subagents,
named sessions) hits:
embedded run agent end: ... isError=true
model=claude-opus-4-7 provider=anthropic
error=Cannot read properties of undefined (reading 'properties')
Disabling the plugin (mv ~/.openclaw/extensions/agntdata-x ~/.openclaw/extensions/agntdata-x.disabled)
immediately restores service.
Root cause in OpenClaw
dist/anthropic-vertex-stream-*.js (the Anthropic adapter):
function convertAnthropicTools(tools, isOAuthToken) {
if (!tools) return [];
return tools.map((tool) => ({
name: ...,
description: tool.description,
input_schema: {
type: "object",
properties: tool.parameters.properties || {}, // ← throws on undefined
required: tool.parameters.required || []
}
}));
}
- No defensive handling of
tool.parameters === undefined
- No
try/catch around per-tool conversion; one broken tool throws and the
whole list-building fails
- No validation at plugin-load time that
parameters (or inputSchema, etc.)
actually exists on registered tools
Proposed fix (ranked by impact/effort)
1. Defensive per-tool conversion (cheap, high value)
Wrap each tool's conversion in try/catch and drop bad tools rather than
crash the whole agent:
function convertAnthropicTools(tools, isOAuthToken) {
if (!tools) return [];
const out = [];
for (const tool of tools) {
try {
const schema = tool.parameters ?? tool.inputSchema; // accept both
if (!schema || typeof schema !== "object") {
log.warn(`tool ${tool.name} has no schema; skipping`);
continue;
}
out.push({
name: ...,
description: tool.description,
input_schema: {
type: "object",
properties: schema.properties || {},
required: schema.required || []
}
});
} catch (err) {
log.warn(`tool ${tool.name} failed schema conversion: ${err.message}`);
}
}
return out;
}
2. Validate at registerTool() time (prevents pollution)
When a plugin calls api.registerTool(), validate that one of the expected
schema keys is present and well-formed. If not, log and reject the
registration rather than silently accept it.
Bonus: accept both parameters and inputSchema (the latter matches
Anthropic's own native format and the MCP spec, so it's a reasonable alias).
Normalize to one canonical internal shape.
3. Surface plugin errors in openclaw status
Today the fact that a plugin broke every agent run only surfaces in
embedded run agent end log lines. A better UX: show broken plugins in
openclaw status with a one-line reason, so users can see "plugin X
failed to load N tools because of schema errors" without tailing logs.
4. Gate-check on plugin install
openclaw plugins install could run a dry conversion pass on every
registerTool() call and refuse to mark the plugin enabled if any tool
fails schema conversion. That would have caught this at install time
rather than at first agent turn.
Repro
# Install a plugin whose index.js uses `inputSchema:` instead of `parameters:`
openclaw plugins install @agntdata/[email protected]
# or any test fixture with registerTool({ name: "foo", inputSchema: {...} })
# Run any Claude agent turn
openclaw exec "say hi"
# Observe: isError=true, error=Cannot read properties of undefined (reading 'properties')
Environment
- OpenClaw 2026.4.15 (041266a)
- Node v25.9.0
- macOS Darwin 25.3.0 arm64
- Affected models: claude-opus-4-7, claude-sonnet-4-6, claude-haiku-4-5
- Affected sessions: main agent, slug-generator, subagents, named sessions
- Not affected: OpenAI models (different adapter; they may have their own
equivalent brittleness — worth a parallel audit)
Severity
High. One broken 3rd-party plugin makes OpenClaw unusable for Anthropic
users. The fix is a ~20-line defensive try/catch.
[Bug]: A single broken plugin's malformed tool schema crashes every agent run (no per-tool isolation in Anthropic adapter)
Summary
When any loaded plugin registers a tool whose schema is stored under the wrong
key (e.g.,
inputSchemainstead ofparameters), the Anthropic tool-conversionadapter throws
TypeError: Cannot read properties of undefined (reading 'properties')while building the tool list, and every subsequent agent run on any Anthropic
model hits
isError=truebefore the model ever sees the user message.The error is never surfaced as an informative "plugin X has a broken tool Y" —
the agent just silently fails every turn.
This turns a single broken 3rd-party plugin into a platform-wide hard outage
for Claude users.
Observed in the wild
Plugin:
@agntdata/[email protected](filing a bug report against themseparately — their schema key is
inputSchema, OpenClaw's contract isparameters).Symptom: every
claude-*agent session (main agent, slug generator, subagents,named sessions) hits:
Disabling the plugin (
mv ~/.openclaw/extensions/agntdata-x ~/.openclaw/extensions/agntdata-x.disabled)immediately restores service.
Root cause in OpenClaw
dist/anthropic-vertex-stream-*.js(the Anthropic adapter):tool.parameters === undefinedtry/catcharound per-tool conversion; one broken tool throws and thewhole list-building fails
parameters(orinputSchema, etc.)actually exists on registered tools
Proposed fix (ranked by impact/effort)
1. Defensive per-tool conversion (cheap, high value)
Wrap each tool's conversion in try/catch and drop bad tools rather than
crash the whole agent:
2. Validate at
registerTool()time (prevents pollution)When a plugin calls
api.registerTool(), validate that one of the expectedschema keys is present and well-formed. If not, log and reject the
registration rather than silently accept it.
Bonus: accept both
parametersandinputSchema(the latter matchesAnthropic's own native format and the MCP spec, so it's a reasonable alias).
Normalize to one canonical internal shape.
3. Surface plugin errors in
openclaw statusToday the fact that a plugin broke every agent run only surfaces in
embedded run agent endlog lines. A better UX: show broken plugins inopenclaw statuswith a one-line reason, so users can see "plugin Xfailed to load N tools because of schema errors" without tailing logs.
4. Gate-check on plugin install
openclaw plugins installcould run a dry conversion pass on everyregisterTool()call and refuse to mark the plugin enabled if any toolfails schema conversion. That would have caught this at install time
rather than at first agent turn.
Repro
Environment
equivalent brittleness — worth a parallel audit)
Severity
High. One broken 3rd-party plugin makes OpenClaw unusable for Anthropic
users. The fix is a ~20-line defensive try/catch.