Defer(...) / NoDefer(...) modifiers while specifying the list of available tools, without modifying the global configuration. This document is a complete reference for this capability.defer_loading field in the product defaults or MCP configuration (see MCP documentation - Lazy Loading for details). These are globally effective default settings. This feature allows you to temporarily adjust the behavior for a single session or a single custom agent without changing the default configuration.Syntax | Description |
Read | Standard tool. Whether to defer is determined by the global default. |
Defer(Glob) | The session/agent forces Glob to use deferred loading (not directly included in the model's tool list, and discoverable through ToolSearch). |
NoDefer(Bash) | The session/agent forces Bash to skip deferred loading (directly included in the model's tool list). |
Defer(mcp__github__*) | Wildcard match that sets the entire group of MCP tools to deferred loading. |
Defer(*) | Set all tools in the current list to deferred loading (extreme trimming). |
* is the only supported wildcard character and matches any character sequence. Other characters (such as ? and []) are treated literally.--tools Parametercodebuddy --tools "Read,Defer(Glob),NoDefer(Bash)"
tools field in ACP and SDK clients is equivalent to the CLI..codebuddy/agents/*.md:---name: code-readerdescription: A read-only code exploration agenttools:- Read- Grep- Defer(Glob) # Makes Glob use lazy loading and be discovered through ToolSearch when needed.- NoDefer(Bash) # Forces Bash to not use lazy loading for this agent, even if lazy loading is enabled by default.---
--allowed-tools / settings.permissions.allow--disallowed-tools / settings.permissions.denymatcher in the hooks configuration# ✖ Error: An error is reported immediately.codebuddy --allowed-tools "Defer(Glob)"# Error: Defer(...) / NoDefer(...) modifiers belong in --tools, not in permission rule fields.# ✔ Correct: Write them separately.codebuddy --tools "...,Defer(Glob)" --allowed-tools "Glob(src/**)"
Priority | Source | Description |
0a | NoDefer(X) matched at any layer | Force non-defer (regardless of what other sources say). |
0b | Defer(X) matched at any layer | Force defer. |
1 | MCP tool-level tools[name].defer_loading | MCP static configuration |
2 | MCP server-level defer_loading | MCP static configuration |
3 | Environment variable CODEBUDDY_DEFER_TOOL_LOADING | Global switch |
4 | User setting settings.deferToolLoading | Global switch |
5 | Built-in default (CodeBuddy Code factory configuration) | Fallback |
NoDefer always takes precedence over Defer: Even if a custom agent writes Defer(X), after CLI --tools writes NoDefer(X), X still does not use lazy loading in this session, because the user's runtime declaration takes priority.NoDefer takes precedence" rule.--allowedTools has duplicates).ToolSearch and DeferExecuteToolDefer(...) appears in the tool list, CodeBuddy Code automatically adds the following two tools (if they are not already in the list):Tool | Function |
ToolSearch | Enables the model to search for and discover lazily loaded tools. |
DeferExecuteTool | Enables the model to actually call lazily loaded tools. |
# Equivalent to codebuddy --tools "Bash,Read,Defer(Edit),ToolSearch,DeferExecuteTool"codebuddy --tools "Bash,Read,Defer(Edit)"
ToolSearch and invoke them through DeferExecuteTool. If either one is missing, Defer(...) means "the model can no longer use this tool". Automatic addition makes the most common usage intuitive.Defer(*) Does Not Sweep ItselfDefer(*), theoretically "all tools" are lazy-loaded, including ToolSearch and DeferExecuteTool themselves, which makes the defer workflow ineffective. To avoid this "self-lockout", automatic addition also adds a NoDefer guardrail to these two tools:codebuddy --tools "Defer(*)"# Behavior is equivalent to:# codebuddy --tools "*,ToolSearch,DeferExecuteTool" + NoDefer(ToolSearch),NoDefer(DeferExecuteTool)
ToolSearch / DeferExecuteTool, so it can search for and invoke other tools that are lazy-loaded.NoDefer(...) and no Defer(...): the user's intent is to bring the tool back to direct invocation, unrelated to the defer workflow.ToolSearch or DeferExecuteTool: idempotent, do not add them again.# Knowing that only Read/Edit will be used this time, temporarily put away other large tools.codebuddy --tools "Read,Edit,Defer(Bash),Defer(Glob),Defer(Grep)"
Read, Edit, and ToolSearch are visible in the model context. When needed, other tools can be invoked through ToolSearch.# Assume Bash is configured for lazy loading by default, but it needs to be directly callable this time.codebuddy --tools "default,NoDefer(Bash)"
default means "all built-in tools" and can be used together with modifiers.---name: explorerdescription: A specialized agent for exploring large repositories that puts away search tools to reduce distractions.tools:- Read- Edit- ToolSearch- Defer(Glob)- Defer(Grep)- Defer(LSP)---
codebuddy --tools "default,Defer(mcp__github__*)"
github pr and github issue through ToolSearch.Error: Invalid --tools value: Invalid tool spec "Defer(Read(*.md))": Defer(...) only accepts a tool name or glob; permission filters like Read(*.md) belong in --allowed-tools, not --tools.
--allowed-tools:codebuddy --tools "Defer(Read)" --allowed-tools "Read(*.md)"
Error: Invalid permission rule "Defer(Glob)" in --allowed-tools / settings.permissions.allow: Defer(...) / NoDefer(...) modifiers belong in --tools, not in permission rule fields.
Defer(NoDefer(X)): Nested modifiers are rejected and have no meaningful semantics.Defer(): Empty content is rejected.defer(Read): Lowercase is not recognized and is rejected as a literal "tool name containing parentheses".tools field in custom agent frontmatter uses lenient validation: a single invalid entry only produces a warning log and is then ignored, without causing CodeBuddy Code to fail to start. Look for prompts similar to the following in the logs to locate the issue:[AgentToolSpec] my-agent: invalid-pattern — Invalid tool spec "Defer(Read(*.md))": ...
--tools input directly from CLI and ACP clients is strictly validated, and invalid syntax causes an immediate error.--allowed-tools and can be used together:codebuddy \\--tools "Read,Write,Defer(Glob)" \\--allowed-tools "Glob(src/**)"
Glob uses lazy loading and does not directly enter the model's tool list.Glob through ToolSearch > DeferExecuteTool, it is still subject to the Glob(src/**) permission constraint.Glob(/etc/*) is rejected according to permission rules.Modifier | Impact on ToolSearch | Impact on DeferExecuteTool |
Defer(X) (X is not originally deferred) | Automatically joins the searchable deferred tool set upon first access. | Automatically register and allow upon first call. |
NoDefer(X) (X is originally deferred) | Does not appear in search results (X has been directly added to the model's tool list and does not need to be searched for). | Returns an error when X is called, guiding direct invocation. |
Error: Tool "Bash" is not deferred in this session (NoDefer modifier). Call it directly instead of via DeferExecuteTool.
--tools. You can only specify tool names or wildcards (such as Defer(mcp__github__*)).Defer(mcp__*) cannot be reverse-enumerated into specific tool names. The lazy indexing of MCP tools still relies on the asynchronous driving process of mcp-server-manager itself.Was this page helpful?
You can also Contact sales or Submit a Ticket for help.
Help us improve! Rate your documentation experience in 5 mins.
Feedback