#Lobster workflow issue
1 messages · Page 1 of 1 (latest)
I pulled the three cl1p snippets before they expired. The two JS files are syntactically valid, so this probably is not a simple JS parse error.
Two likely fixes from what you pasted:
- Your LLM step can run for 180s, but the Lobster tool itself times out separately. If you’re invoking this with the default Lobster timeout, it can die before
invoke-llm-task.jsfinishes. Run it with a larger Lobster timeout, e.g.:
{
"action": "run",
"pipeline": "/home/admin/.openclaw/workspace-dba-scout/<your-workflow>.yaml",
"timeoutMs": 240000,
"maxStdoutBytes": 2097152
}
- If the error is coming from
render-email-html.jswith “Expected input JSON to contain a leads array”, thenextract-llm-json.jsis probably passing the llm-task tool envelope instead of the inner JSON. Make the render script tolerant of the officialllm-taskshape:
const raw = JSON.parse(input);
const data = raw?.details?.json ?? raw?.json ?? raw;
That should go where you currently have:
const data = JSON.parse(input);
Please paste the exact error plus:
openclaw --version
openclaw status --all
If this fixed it, right-click the solution message → Apps → ✅ Mark Solution so Answer Overflow indexes it.
This is the contents of
Looks like that message got cut off. Please paste the rest, especially the exact error output and which file/content it belongs to. Also include openclaw --version when you can.
This is the contents of file debug-draft-email-stderr.txt
Gateway HTTP request failed
URL: http://127.0.0.1:18789/tools/invoke
Status: 500 Internal Server Error
Raw response:
{"ok":false,"error":{"type":"tool_error","message":"tool execution failed"}}
That error means the failure is inside the Gateway tool invocation, before render-email-html.js runs. debug-draft-email-stderr.txt is only showing the wrapper error from /tools/invoke; the real cause should be in the Gateway logs.
Please run:
openclaw --version
openclaw logs --follow
Then rerun the workflow and look for the llm-task error around the same timestamp. Common causes here are:
llm-taskis not enabled or not allowed for the agent.- provider/model could not be resolved for
llm-task. - invalid or unsupported
thinking: "low"for the selected model. - timeout: your inner request allows 180s, but plugin/default/gateway timeout may still be lower.
- schema validation failed because the model returned JSON that did not match the schema.
Also check config has both the plugin enabled and the tool allowed, per docs https://docs.openclaw.ai/tools/llm-task:
{
"plugins": {
"entries": {
"llm-task": { "enabled": true }
}
},
"agents": {
"list": [
{
"id": "main",
"tools": { "alsoAllow": ["llm-task", "lobster"] }
}
]
}
}
If you paste the openclaw logs --follow lines for the failed llm-task call, we can pin it down instead of guessing.
These ar the logs
00:08:31
error
diagnostic
lane task error: lane=main durationMs=764 error="FailoverError: Unknown model: qwen/qwen3.6-35b-a3b"
00:08:31
error
diagnostic
lane task error: lane=session:agent:main:explicit:llm-task-1778800111041 durationMs=773 error="FailoverError: Unknown model: qwen/qwen3.6-35b-a3b"
00:08:31
error
[tools] lobster failed: workflow command failed (1): sh -c 'node /home/admin/.openclaw/workspace-dba-scout/lobster-scripts/invoke-llm-task.js 2> /home/admin/.openclaw/workspace-dba-scout/debug-draft-email-stderr.txt' raw_params={"action":"run","pipeline":"/home/admin/.openclaw/workspace-dba-scout/sql-leads-draft.lobster","timeoutMs":600000,"maxStdoutBytes":512000}
00:08:31
error
[tools] lobster failed: workflow command failed (1): sh -c 'node /home/admin/.openclaw/workspace-dba-scout/lobster-scripts/invoke-llm-task.js 2> /home/admin/.openclaw/workspace-dba-scout/debug-draft-email-stderr.txt' raw_params={"action":"run","pipeline":"/home/admin/.openclaw/workspace-dba-scout/sql-leads-draft.lobster","timeoutMs":600000,"maxStdoutBytes":512000}
That pins it down: Lobster is fine; the LLM step is failing because OpenClaw cannot resolve this configured model:
qwen/qwen3.6-35b-a3b
So invoke-llm-task.js calls /tools/invoke, llm-task starts an embedded agent run, and that run immediately fails with FailoverError: Unknown model.
Fix: change whatever is selecting that model to a model that exists in your OpenClaw model catalog, or remove the llm-task model override so it uses your normal default.
Places to check:
openclaw models status
openclaw config get plugins.entries.llm-task
openclaw config get agents.defaults.model
openclaw config get agents.defaults.models
If you set it specifically for the plugin, it will be under:
{
"plugins": {
"entries": {
"llm-task": {
"config": {
"defaultProvider": "...",
"defaultModel": "..."
}
}
}
}
}
Either set defaultProvider + defaultModel to a known-good configured model, or delete those two fields and let llm-task inherit agents.defaults.model.
Docs:
https://docs.openclaw.ai/tools/llm-task
https://docs.openclaw.ai/concepts/models
For current model recommendations, ask in #models since the available/community-tested model list changes fast.
You can find the results of those here https://cl1p.net/4563
Yep, this output explains the failure.
Your OpenClaw default is:
lmstudio/qwen/qwen3.6-35b-a3b
When llm-task runs, the LM Studio model id becomes:
qwen/qwen3.6-35b-a3b
LM Studio/OpenClaw is rejecting that as unknown. So either LM Studio does not currently expose that exact key, or the key in OpenClaw config does not match LM Studio’s actual model key.
Run this on the machine where LM Studio is running:
curl http://localhost:1234/api/v1/models
Look for the exact key field, then set OpenClaw to lmstudio/<that-key>.
Example shape only:
openclaw models set lmstudio/qwen/the-exact-key-from-lm-studio
openclaw gateway restart
Also, your fallback has a mismatch:
Fallbacks: lmstudio/gemma-4-31b
but configured models show:
lmstudio/google/gemma-4-31b
and alias:
local-gemma
So that fallback probably should be local-gemma or lmstudio/google/gemma-4-31b, not lmstudio/gemma-4-31b.
Docs for the exact LM Studio key behavior: https://docs.openclaw.ai/providers/lmstudio
After changing it, rerun:
openclaw models status
Then rerun the Lobster workflow.
"lmstudio": {
"baseUrl": "http://beelink:1234/v1",
Ah, then use the LM Studio host from your config, not localhost:
curl http://beelink:1234/api/v1/models
Compare the returned key values with your OpenClaw model ids. If LM Studio returns a key like:
"key": "qwen/qwen3.6-35b-a3b-something"
then OpenClaw should use:
lmstudio/qwen/qwen3.6-35b-a3b-something
Also verify the OpenClaw machine can resolve beelink:
curl http://beelink:1234/v1/models
If that fails, use the Beelink’s LAN IP in models.providers.lmstudio.baseUrl instead of the hostname.
{
"data": [
{
"id": "qwen/qwen3.6-35b-a3b",
"object": "model",
"owned_by": "organization_owner"
},
{
"id": "unsloth/qwen3.6-27b",
"object": "model",
"owned_by": "organization_owner"
},
{
"id": "google/gemma-4-31b",
"object": "model",
"owned_by": "organization_owner"
},
{
"id": "qwen/qwen3.6-27b",
"object": "model",
"owned_by": "organization_owner"
},
{
"id": "text-embedding-nomic-embed-text-v1.5",
"object": "model",
"owned_by": "organization_owner"
}
],
"object": "list"
}
That response is from the OpenAI-compatible endpoint /v1/models. It proves inference can see the model, but it is not the endpoint OpenClaw’s LM Studio provider uses for model discovery.
OpenClaw’s LM Studio provider discovers models from:
curl http://beelink:1234/api/v1/models
That response should have models[].key, not data[].id. If /api/v1/models fails or returns nothing useful, OpenClaw may still show your manually configured names but fail at runtime with Unknown model.
Pragmatic fix: add the LM Studio models explicitly under models.providers.lmstudio.models in ~/.openclaw/openclaw.json, not only under agents.defaults.models:
{
"models": {
"providers": {
"lmstudio": {
"baseUrl": "http://beelink:1234/v1",
"api": "openai-completions",
"models": [
{
"id": "qwen/qwen3.6-35b-a3b",
"name": "Qwen 3.6 35B A3B",
"reasoning": false,
"input": ["text"],
"contextWindow": 128000,
"maxTokens": 8192
},
{
"id": "google/gemma-4-31b",
"name": "Gemma 4 31B",
"reasoning": false,
"input": ["text"],
"contextWindow": 128000,
"maxTokens": 8192
}
]
}
}
}
}
Then restart and test:
openclaw gateway restart
openclaw models status
Also fix the fallback while you’re there: use lmstudio/google/gemma-4-31b or local-gemma, not lmstudio/gemma-4-31b.
They are already under lmstudio
{
"id": "qwen/qwen3.6-35b-a3b",
"name": "Qwen3.6 35B A3B",
"reasoning": false,
"input": [
"text",
"image"
],
"cost": {
"input": 0,
"output": 0,
"cacheRead": 0,
"cacheWrite": 0
},
"compat": {
"supportsReasoningEffort": false
},
"contextWindow": 262144,
"contextTokens": 200000,
"maxTokens": 8192
}
Good catch. If that model is already under models.providers.lmstudio.models, then the important clue is the error text:
Unknown model: qwen/qwen3.6-35b-a3b
It is missing the lmstudio/ provider prefix. OpenClaw is trying to resolve provider qwen, model qwen3.6-35b-a3b, instead of provider lmstudio, model qwen/qwen3.6-35b-a3b.
So the likely bug is in invoke-llm-task.js or config/env around that script, not in the LM Studio model catalog.
Fix the payload sent to /tools/invoke so it calls llm-task with either:
{
"provider": "lmstudio",
"model": "qwen/qwen3.6-35b-a3b"
}
or no provider / model fields at all, letting llm-task inherit:
{
"primary": "lmstudio/qwen/qwen3.6-35b-a3b"
}
Do not send:
{
"model": "qwen/qwen3.6-35b-a3b"
}
if the wrapper interprets that as a full OpenClaw model ref and splits it into provider/model.
Please paste invoke-llm-task.js too. That is probably where the prefix is being dropped or split incorrectly.
This is the invoke script
let s = "";
process.stdin.on("data", c => {
s += c;
});
process.stdin.on("end", async () => {
try {
const args = JSON.parse(s);
const port = process.env.OPENCLAW_GATEWAY_PORT || "18789";
const baseUrl = process.env.OPENCLAW_GATEWAY_URL || `http://127.0.0.1:${port}`;
const token = process.env.OPENCLAW_GATEWAY_TOKEN || process.env.SHARED_GATEWAY_TOKEN || "";
const url = `${baseUrl.replace(/\/$/, "")}/tools/invoke`;
const headers = { "content-type": "application/json" };
if (token) headers.authorization = `Bearer ${token}`;
const payload = {
tool: "llm-task",
action: "json",
args
};
const res = await fetch(url, {
method: "POST",
headers,
body: JSON.stringify(payload)
});
const text = await res.text();
if (!res.ok) {
console.error("Gateway HTTP request failed");
console.error("URL:", url);
console.error("Status:", res.status, res.statusText);
console.error("Raw response:");
console.error(text);
process.exit(1);
}
let parsed;
try {
parsed = JSON.parse(text);
} catch (err) {
console.error("Gateway returned non-JSON response");
console.error("Raw response:");
console.error(text);
process.exit(1);
}
if (parsed && parsed.ok === false) {
console.error("llm-task tool returned ok=false");
console.error(JSON.stringify(parsed, null, 2));
process.exit(1);
}
process.stdout.write(text);
} catch (err) {
console.error("invoke-llm-task.js failed before/during request");
console.error(err && err.stack ? err.stack : String(err));
process.exit(1);
}
});
Thanks, that script explains the shape. The invoke wrapper is not doing any model splitting itself; it just passes args through.
Two solid fixes:
- Make the
/tools/invokecall use the same agent/session as yoursqlsetup. Right now direct HTTP invoke defaults to the main session unless you passsessionKey.
Change:
const payload = {
tool: "llm-task",
action: "json",
args
};
to:
const payload = {
tool: "llm-task",
action: "json",
sessionKey: process.env.OPENCLAW_SESSION_KEY || "agent:sql:main",
args
};
- To remove any ambiguity, force the model as separate provider/model fields before building the payload:
args.provider = args.provider || "lmstudio";
args.model = args.model || "qwen/qwen3.6-35b-a3b";
Put that immediately after:
const args = JSON.parse(s);
So the block becomes:
const args = JSON.parse(s);
args.provider = args.provider || "lmstudio";
args.model = args.model || "qwen/qwen3.6-35b-a3b";
const port = process.env.OPENCLAW_GATEWAY_PORT || "18789";
Then rerun. If the error changes from Unknown model: qwen/qwen3.6-35b-a3b to something else, we’re past model resolution and onto the next real issue.
That fixed it
Glad that fixed it 🎉
Root cause was the direct /tools/invoke call defaulting to the wrong session/model context, so llm-task saw qwen/... as the provider/model ref instead of lmstudio + qwen/....
Please right-click the solution message → Apps → ✅ Mark Solution so Answer Overflow indexes it for the next person.