feat: add tool allow/deny profiles with per-agent and per-provider filtering

Implements configurable tool filtering with four built-in profiles
(minimal, messaging, coding, full), global and per-agent/per-provider
allow/deny lists with glob pattern support, and defense-in-depth
enforcement at both tool listing and execution time.

New: src/tools/policy.ts (ToolPolicy engine), src/tools/policy.test.ts (37 tests)
Modified: config schema, tool registry, tool executor, NativeAgent,
AgentOrchestrator, daemon wiring, gateway tool handler, test mocks
This commit is contained in:
William Valentin
2026-02-06 15:30:34 -08:00
parent 8238d3e981
commit ee0af0cc06
13 changed files with 794 additions and 8 deletions
+39
View File
@@ -1,4 +1,5 @@
import type { Tool, ToolInputSchema } from './types.js';
import type { ToolPolicy, ToolPolicyContext } from './policy.js';
export interface AnthropicToolDef {
name: string;
@@ -17,6 +18,7 @@ export interface OpenAIToolDef {
export class ToolRegistry {
private tools: Map<string, Tool> = new Map();
private _policy?: ToolPolicy;
register(tool: Tool): void {
if (this.tools.has(tool.name)) {
@@ -37,6 +39,22 @@ export class ToolRegistry {
return Array.from(this.tools.values());
}
/** Set the tool policy for filtering. */
setPolicy(policy: ToolPolicy): void {
this._policy = policy;
}
/** Get the tool policy (if set). */
getPolicy(): ToolPolicy | undefined {
return this._policy;
}
/** Return tools filtered by the policy for a given context. */
filteredList(context?: ToolPolicyContext): Tool[] {
if (!this._policy) return this.list();
return this._policy.filterTools(this.list(), context);
}
toAnthropicFormat(): AnthropicToolDef[] {
return this.list().map(t => ({
name: t.name,
@@ -45,6 +63,15 @@ export class ToolRegistry {
}));
}
/** Return Anthropic-format tools filtered by policy. */
filteredToAnthropicFormat(context?: ToolPolicyContext): AnthropicToolDef[] {
return this.filteredList(context).map(t => ({
name: t.name,
description: t.description,
input_schema: t.inputSchema,
}));
}
toOpenAIFormat(): OpenAIToolDef[] {
return this.list().map(t => ({
type: 'function' as const,
@@ -55,4 +82,16 @@ export class ToolRegistry {
},
}));
}
/** Return OpenAI-format tools filtered by policy. */
filteredToOpenAIFormat(context?: ToolPolicyContext): OpenAIToolDef[] {
return this.filteredList(context).map(t => ({
type: 'function' as const,
function: {
name: t.name,
description: t.description,
parameters: t.inputSchema,
},
}));
}
}