How Agent Tool Assignments Work in oh-my-claudecode: A Complete Customization Guide
Agent tool assignments in oh-my-claudecode start with full access to all built-in tools, then apply restrictions through either front-matter disallowedTools declarations or explicit runtime tools overrides.
Every agent in the oh-my-claudecode framework begins with unrestricted access to the complete toolkit, including Read, Write, Edit, Glob, Grep, WebSearch, and WebFetch. The system determines final agent tool assignments through a cascading restriction mechanism that combines static markdown configuration with dynamic runtime overrides. This architecture allows you to create specialized, read-only agents like architect while maintaining the flexibility to customize tool access for specific projects without touching core source code.
The Two-Layer Agent Tool Assignment System
The framework implements a hierarchical approach to agent tool assignments where permissions flow from broad to specific:
| Restriction Source | Mechanism | Location |
|---|---|---|
disallowedTools front-matter |
Removes specific tools from the default full set (e.g., disabling Write and Edit for the architect agent) |
agents/architect.md (line 6) |
Explicit tools override |
Replaces the entire toolbox with a custom array or restriction map ({tools:{read:true,…}}) |
Runtime via src/agents/definitions.ts |
If neither restriction layer is present, the agent retains all available tools. This default-everything approach ensures agents are never accidentally crippled while still supporting precise capability limiting.
Core Files Managing Tool Assignments
Understanding agent tool assignments requires familiarity with three critical files that handle parsing, transformation, and registry composition:
src/agents/utils.ts contains the parsing utilities. The parseDisallowedTools(agentName: string) function reads each agent's markdown front-matter and returns a string array of tool names to block. The companion createAgentToolRestrictions(blockedTools: string[]) helper converts these block lists into the {tools: {tool:false}} shape required by the Claude Code SDK.
src/agents/definitions.ts serves as the central registry through getAgentDefinitions(). This function orchestrates the final toolset by merging static TypeScript configurations, markdown-based disallowedTools lists, and any runtime overrides supplied via PluginConfig or direct API calls.
agents/*.md files (such as agents/architect.md) contain the authoritative per-agent configuration. The front-matter YAML declares which tools are explicitly forbidden for that specific agent personality.
The Tool Assignment Pipeline
The framework applies agent tool assignments through a predictable five-step sequence:
Step 1: Loading Static Definitions
Each agent (e.g., architectAgent, executorAgent) exports from its own TypeScript file (e.g., src/agents/architect.ts). At this stage, the tools property is intentionally undefined, signaling that the agent should inherit the full default toolkit.
Step 2: Parsing Front-Matter Disallowed Tools
When getAgentDefinitions() executes, it invokes parseDisallowedTools(name) for each agent. This function opens agents/<name>.md, extracts the disallowedTools: line, splits the comma-separated values into an array, and returns the blocked tool list.
Step 3: Creating Restriction Maps
If a disallowed list exists, the system prepares it for the SDK. While the framework handles this automatically during registry creation, the createAgentToolRestrictions helper allows manual construction of restriction objects when building custom plugins.
Step 4: Applying Runtime Overrides
User-supplied configuration from .omc/plans/*.md or ~/.claude/settings.json may contain a tools field under config.agents.<name>. These values, along with programmatic overrides passed to getAgentDefinitions(options), replace any existing tool list—including the auto-generated block list from step 2.
Step 5: Composing Final Definitions
The resulting agent object contains description, prompt, model, and either tools (an explicit allow list) or disallowedTools (a subtraction from the full set). This final configuration is returned to the Claude-Code orchestration layer.
Customizing Agent Tool Assignments
You can customize agent tool assignments at three different integration points depending on your needs.
Blocking Tools via Front-Matter
The simplest method uses YAML front-matter in the agent's markdown definition. This approach requires no code changes and persists across updates.
# agents/architect.md
---
name: architect
description: Strategic Architecture & Debugging Advisor
model: claude-opus-4-6
level: 3
disallowedTools: Write, Edit # ← architect becomes read-only
---
When parseDisallowedTools('architect') processes this file, it returns ['Write','Edit']. The resulting agent can execute Read, Glob, and Grep operations but cannot modify files.
Overriding Tools via Configuration
Project-specific customizations belong in your configuration files. This method completely replaces the default toolset rather than subtracting from it.
// .omc/config.json
{
"agents": {
"architect": {
"tools": ["Read", "Glob", "Grep", "lsp_diagnostics"]
}
}
}
When loadConfig() reads this file, the override?.tools branch in getAgentDefinitions replaces the architect's toolbox with exactly the four tools specified, ignoring any disallowedTools settings from the markdown.
Programmatic Restrictions
For plugin developers or dynamic scenarios, use the utility functions to construct restriction maps manually.
import { createAgentToolRestrictions } from './src/agents/utils.js';
import { getAgentDefinitions } from './src/agents/definitions.js';
const customDefs = getAgentDefinitions({
overrides: {
executor: {
tools: createAgentToolRestrictions(['WebFetch', 'WebSearch']).tools
},
},
});
Here, the executor agent loses web-search capabilities while retaining all other tools. The createAgentToolRestrictions function generates the proper nested object structure that the SDK expects for capability limiting.
Summary
- Default posture: Every agent begins with unrestricted access to all built-in tools when no
toolsordisallowedToolsfields are present. - Subtractive restriction: Use
disallowedToolsin an agent's markdown front-matter (e.g.,agents/architect.md) to remove specific capabilities while keeping the rest. - Additive replacement: Supply a
toolsarray viaPluginConfigor runtime overrides to define an exact allow list, bypassing any markdown restrictions. - Implementation hub: The
getAgentDefinitionsfunction insrc/agents/definitions.tscoordinates these layers, callingparseDisallowedToolsfromsrc/agents/utils.tswhen needed.
Frequently Asked Questions
What is the default toolset for agents in oh-my-claudecode?
By default, every agent receives all available tools including Read, Write, Edit, Glob, Grep, WebSearch, and WebFetch. The TypeScript agent definitions (e.g., src/agents/architect.ts) leave the tools property undefined to signal this full-access mode. Restrictions are applied only when disallowedTools or explicit tools configurations are detected.
How does the disallowedTools front-matter field work?
The disallowedTools field in an agent's markdown file (located in agents/*.md) contains a comma-separated list of tool names to remove from that agent's default toolbox. The parseDisallowedTools function in src/agents/utils.ts parses this line, splits it into an array, and passes it to the restriction logic. For example, disallowedTools: Write, Edit creates a read-only agent that can analyze code but cannot modify it.
Can I add tools to an agent that are disabled by default?
Yes. Because the explicit tools override replaces the entire assignment rather than merging with restrictions, you can supply a complete array including any tools you need. Configure this in your .omc/config.json or via the overrides parameter in getAgentDefinitions. This approach supersedes both the default full-access mode and any disallowedTools settings from the agent's markdown.
Where should I define custom tool restrictions for my project?
Place project-specific agent tool assignments in .omc/config.json or your plan files within the .omc/plans/ directory. These user-provided configurations are loaded by the loadConfig() mechanism and passed to getAgentDefinitions as runtime overrides. This keeps your customizations separate from the core oh-my-claudecode source code and persists them across framework updates.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →