How do permissions and pattern approval work?
how do permissions work? does the notion of "pre-approve certain patterns" work well? and what about "the user wants to approve this just for this session"?
Now I have a good understanding. Let me summarize what I found about permissions:
##How Permissions Work in DeepAgentsJS
Based on my exploration of the codebase, here's how permissions work:
###1. The HITL (Human-in-the-Loop) System via interruptOn
The primary permission mechanism is through the interruptOn configuration, which uses LangGraph's interrupt capabilities via the humanInTheLoopMiddleware:
const agent = createDeepAgent({
tools: [getWeather, sampleTool],
interruptOn: {
// Boolean: true = require approval (with all decisions allowed)
sample_tool: true,
// Boolean: false = auto-approve (no interrupt)
get_weather: false,
// Object: fine-grained control
get_soccer_scores: {
allowedDecisions: ["approve", "edit", "reject"]
},
},
checkpointer: new MemorySaver(), // Required for HITL
});
###2. Pre-Approve Certain Patterns: Not Yet Implemented
Looking at the code, there's no pattern-based pre-approval system. The interruptOn config works on exact tool names, not patterns or wildcards.
However, there's an interesting concept in Skills: allowedTools in SKILL.md frontmatter:
---
name: web-research
description: Research skill
allowed-tools: read_file write_file search_web
---
But this is currently only for display (showing in the system prompt what tools a skill uses). There's no actual enforcement or integration with the HITL middleware. From skills.ts:
if (skill.allowedTools && skill.allowedTools.length > 0) {
lines.push(` → Allowed tools: ${skill.allowedTools.join(", ")}`);
}
So pre-approving patterns doesn't work well yet — it's essentially just documentation. To pre-approve tools, you'd need to explicitly list each tool name in interruptOn: { tool_name: false }.
###3. Session-Based Approval: Not Implemented
There's no built-in concept of "approve for this session only". The current system is:
- Config-based: You define
interruptOnat agent creation time - Per-invocation: Each tool call that matches
interruptOntriggers an interrupt - Resume with decisions: You resume with
Command({ resume: { decisions: [...] } })
The decisions (approve, edit, reject) apply to that specific tool call, not to future calls of the same tool. So if you approve get_weather once, it will still interrupt the next time get_weather is called.
###Potential Workarounds
If you wanted session-based approval, you'd need to:
- Modify
interruptOnat runtime - not currently supported cleanly - Track approved tools in state and build custom middleware that checks this before interrupting
- Use the CLI's
--auto-approveflag (mentioned in CLI README) which likely bypasses all HITL entirely
###CLI Auto-Approve
The CLI mentions:
deepagents --auto-approve # Skip human-in-the-loop prompts
This appears to be a global override that skips all HITL, not a fine-grained pattern system.
##Summary
| Feature | Status | How it works |
|---|---|---|
| Pre-approve by tool name | ✅ Works | interruptOn: { tool_name: false } |
| Pre-approve by pattern/wildcard | ❌ Not implemented | Would need custom middleware |
| Session-based approval | ❌ Not implemented | No memory of past approvals |
Skill allowedTools | 🟡 Display only | Shows in prompt, not enforced |
| Global auto-approve | ✅ CLI flag | --auto-approve |
The architecture is extensible — you could build custom middleware to track session-approved tools in state and conditionally bypass HITL — but it's not built-in yet.
END OF POST