Skip to content

Commit 748a217

Browse files
committed
fix(tools): skip allowlist guard when tools are explicitly disabled
When an embedded model run (e.g. llm-task from a Lobster workflow) intentionally disables tools, the explicit tool allowlist guard from the parent session's alsoAllow config should not fire. Previously it would error with 'No callable tools remain' because the allowlist sources existed but no tools were callable (by design). Return null early from buildEmptyExplicitToolAllowlistError when disableTools is true, since disabling tools is an intentional choice that should not be treated as a configuration failure. Fixes #74019
1 parent 5ecd01f commit 748a217

2 files changed

Lines changed: 8 additions & 9 deletions

File tree

src/agents/tool-allowlist-guard.test.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,15 @@ describe("tool allowlist guard", () => {
1717
expect(error?.message).toContain("no registered tools matched");
1818
});
1919

20-
it("fails closed for runtime toolsAllow when tools are disabled", () => {
20+
it("skips guard when tools are explicitly disabled for the run", () => {
2121
const error = buildEmptyExplicitToolAllowlistError({
2222
sources: [{ label: "runtime toolsAllow", entries: ["query_db"] }],
2323
callableToolNames: [],
2424
toolsEnabled: true,
2525
disableTools: true,
2626
});
2727

28-
expect(error?.message).toContain("runtime toolsAllow: query_db");
29-
expect(error?.message).toContain("tools are disabled for this run");
28+
expect(error).toBeNull();
3029
});
3130

3231
it("fails closed when the selected model cannot use requested tools", () => {

src/agents/tool-allowlist-guard.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,19 @@ export function buildEmptyExplicitToolAllowlistError(params: {
2020
toolsEnabled: boolean;
2121
disableTools?: boolean;
2222
}): Error | null {
23+
if (params.disableTools === true) {
24+
return null;
25+
}
2326
const callableToolNames = params.callableToolNames.map(normalizeToolName).filter(Boolean);
2427
if (params.sources.length === 0 || callableToolNames.length > 0) {
2528
return null;
2629
}
2730
const requested = params.sources
2831
.map((source) => `${source.label}: ${source.entries.map(normalizeToolName).join(", ")}`)
2932
.join("; ");
30-
const reason =
31-
params.disableTools === true
32-
? "tools are disabled for this run"
33-
: params.toolsEnabled
34-
? "no registered tools matched"
35-
: "the selected model does not support tools";
33+
const reason = params.toolsEnabled
34+
? "no registered tools matched"
35+
: "the selected model does not support tools";
3636
return new Error(
3737
`No callable tools remain after resolving explicit tool allowlist (${requested}); ${reason}. Fix the allowlist or enable the plugin that registers the requested tool.`,
3838
);

0 commit comments

Comments
 (0)