Add run-level auto permission mode

- add LLM-based auto permission classifier for permission-gated tool calls
- store run-level permission mode and auto permission decision events
- auto-approve low-risk calls, and bubble auto-denied calls to manual approval
- show auto-denied reasons in chat and auto-approved labels below tool cards
- add BYOK setting for the auto-permission decision model
This commit is contained in:
Ramnique Singh 2026-06-03 07:57:50 +05:30
parent 8a8b78071d
commit d47cab6a0f
15 changed files with 641 additions and 85 deletions

View file

@ -17,10 +17,15 @@ export const LlmModelConfig = z.object({
headers: z.record(z.string(), z.string()).optional(),
model: z.string().optional(),
models: z.array(z.string()).optional(),
knowledgeGraphModel: z.string().optional(),
meetingNotesModel: z.string().optional(),
liveNoteAgentModel: z.string().optional(),
autoPermissionDecisionModel: z.string().optional(),
})).optional(),
// Per-category model overrides (BYOK only — signed-in users always get
// the curated gateway defaults). Read by helpers in core/models/defaults.ts.
knowledgeGraphModel: z.string().optional(),
meetingNotesModel: z.string().optional(),
liveNoteAgentModel: z.string().optional(),
autoPermissionDecisionModel: z.string().optional(),
});

View file

@ -21,6 +21,7 @@ export const StartEvent = BaseRunEvent.extend({
agentName: z.string(),
model: z.string(),
provider: z.string(),
permissionMode: z.enum(["manual", "auto"]).optional(),
// useCase/subUseCase tag the run for analytics. Optional on read so legacy
// run files written before these fields existed still parse cleanly.
useCase: z.enum([
@ -110,6 +111,15 @@ export const ToolPermissionResponseEvent = BaseRunEvent.extend({
scope: z.enum(["once", "session", "always"]).optional(),
});
export const ToolPermissionAutoDecisionEvent = BaseRunEvent.extend({
type: z.literal("tool-permission-auto-decision"),
toolCallId: z.string(),
toolCall: ToolCallPart,
permission: ToolPermissionMetadata.optional(),
decision: z.enum(["allow", "deny"]),
reason: z.string(),
});
export const RunErrorEvent = BaseRunEvent.extend({
type: z.literal("error"),
error: z.string(),
@ -134,6 +144,7 @@ export const RunEvent = z.union([
AskHumanResponseEvent,
ToolPermissionRequestEvent,
ToolPermissionResponseEvent,
ToolPermissionAutoDecisionEvent,
RunErrorEvent,
RunStoppedEvent,
]);
@ -166,6 +177,7 @@ export const Run = z.object({
agentId: z.string(),
model: z.string(),
provider: z.string(),
permissionMode: z.enum(["manual", "auto"]).optional(),
useCase: UseCase.optional(),
subUseCase: z.string().optional(),
log: z.array(RunEvent),
@ -185,6 +197,7 @@ export const CreateRunOptions = z.object({
agentId: z.string(),
model: z.string().optional(),
provider: z.string().optional(),
permissionMode: z.enum(["manual", "auto"]).optional(),
useCase: UseCase.optional(),
subUseCase: z.string().optional(),
});