MintClaw's tools configuration is located in the tools field of config.json.
Related: Per-agent tool filtering is configured in each agent's
AGENT.mdfrontmatter, not under the top-leveltoolssection. See the Configuration Guide.
{
"tools": {
"web": {
...
},
"mcp": {
...
},
"exec": {
...
},
"cron": {
...
},
"skills": {
...
}
}
}Before tool results are sent to the LLM, MintClaw can filter sensitive values (API keys, tokens, secrets) from the output. This prevents the LLM from seeing its own credentials.
See Sensitive Data Filtering for full documentation.
| Config | Type | Default | Description |
|---|---|---|---|
filter_sensitive_data |
bool | true |
Enable/disable filtering |
filter_min_length |
int | 8 |
Minimum content length to trigger filtering |
Tool approvals default to required. To run an explicitly trusted deployment
without approval prompts, set:
{
"tools": {
"approval": {
"mode": "allow_all"
}
}
}| Config | Type | Default | Description |
|---|---|---|---|
tools.approval.mode |
string | required |
required uses approval hooks and operator confirmation; allow_all bypasses both |
tools.approval.bypass_node_targets |
string[] | [] |
Exact node target aliases that bypass tool and operator approval while mode remains required |
allow_all is a global unattended-operation mode. It bypasses only the
approval boundary. Pairing, target/profile authorization, discovery revisions,
node policy, broker identity checks, and timeout/output limits still apply.
Subagents also remain limited to targets and profiles granted to them. Run
mintclaw doctor to surface this mode as a high-risk finding.
To bypass approval only for explicitly trusted node targets, keep the global
mode at required and list their configured execution-target aliases:
{
"tools": {
"approval": {
"mode": "required",
"bypass_node_targets": ["vpn"]
}
}
}The bypass applies to every current or future first-party node tool carrying
MintClaw's internal trusted-node capability when its call explicitly includes
an exact listed target. An injected or replacement tool cannot gain the bypass
by using a nodes_* name or wrapping a first-party tool. The validated tool
instance is bound through execution, so a concurrent registry replacement
cannot inherit its approval. Other targets, calls that omit the target, and
non-node tools continue through the configured approval hooks. Target aliases
must exist in execution.targets; duplicates, unknown targets, and combining
bypass_node_targets with allow_all are rejected.
mintclaw doctor reports the scoped bypass as a high-risk finding.
The built-in request_user_input tool lets foreground turns and durable
background tasks pause for an authorized user answer and resume across process
restarts.
| Config | Type | Default | Description |
|---|---|---|---|
tools.request_user_input.enabled |
bool | true |
Allow new model-requested questions |
tools.request_user_input.default_timeout_seconds |
int | 3600 |
Default wait, from 60 seconds to the configured maximum |
tools.request_user_input.max_timeout_seconds |
int | 86400 |
Maximum model-requested wait, at most 24 hours |
tools.request_user_input.retention_hours |
int | 168 |
Retain terminal interaction records before pruning |
Disabling the tool prevents new questions but does not discard pending durable state. Human approval remains opt-in through a trusted approval hook.
See Durable Human Interaction for answer formats, approval behavior, restart semantics, storage, and debugging.
Web tools are used for web search and fetching.
General settings for fetching and processing webpage content.
| Config | Type | Default | Description |
|---|---|---|---|
enabled |
bool | true | Enable the webpage fetching capability. |
fetch_limit_bytes |
int | 10485760 | Maximum size of the webpage payload to fetch, in bytes (default is 10MB). |
format |
string | "plaintext" | Output format of the fetched content. Options: plaintext or markdown (recommended). |
| Config | Type | Default | Description |
|---|---|---|---|
enabled |
bool | false | Enable Brave search |
api_key |
string | - | Brave Search API key |
api_keys |
string[] | - | Multiple API keys for rotation (takes priority over api_key) |
max_results |
int | 5 | Maximum number of results |
| Config | Type | Default | Description |
|---|---|---|---|
enabled |
bool | true | Enable DuckDuckGo search |
max_results |
int | 5 | Maximum number of results |
Gemini search uses Gemini with Google Search grounding. It returns an AI-synthesized answer with citations from Google Search.
| Config | Type | Default | Description |
|---|---|---|---|
enabled |
bool | false | Enable Gemini Google Search |
api_key |
string | - | Google Gemini API key |
model |
string | gemini-2.5-flash |
Gemini model used for search |
max_results |
int | 5 | Maximum number of citations |
{
"tools": {
"web": {
"gemini": {
"enabled": true,
"api_key": "YOUR_GEMINI_API_KEY",
"model": "gemini-2.5-flash",
"max_results": 5
}
}
}
}Baidu Search uses the Qianfan AI Search API, which is AI-powered and optimized for Chinese-language queries.
| Config | Type | Default | Description |
|---|---|---|---|
enabled |
bool | false | Enable Baidu Search |
api_key |
string | - | Qianfan API key |
base_url |
string | https://qianfan.baidubce.com/v2/ai_search/web_search |
Baidu Search API URL |
max_results |
int | 5 | Maximum number of results |
{
"tools": {
"web": {
"baidu_search": {
"enabled": true,
"api_key": "YOUR_BAIDU_QIANFAN_API_KEY",
"max_results": 10
}
}
}
}| Config | Type | Default | Description |
|---|---|---|---|
enabled |
bool | false | Enable Perplexity search |
api_key |
string | - | Perplexity API key |
api_keys |
string[] | - | Multiple API keys for rotation (takes priority over api_key) |
max_results |
int | 5 | Maximum number of results |
Kagi Search uses the official Kagi OpenAPI client for POST /search and returns normal web results from data.search.
| Config | Type | Default | Description |
|---|---|---|---|
enabled |
bool | false | Enable Kagi Search |
api_key |
string | - | Kagi API key |
api_keys |
string[] | - | Multiple API keys for rotation (takes priority over api_key) |
base_url |
string | https://kagi.com/api/v1/search |
Kagi Search API endpoint |
max_results |
int | 5 | Maximum number of results |
{
"tools": {
"web": {
"provider": "kagi",
"kagi": {
"enabled": true,
"max_results": 5,
"base_url": "https://kagi.com/api/v1/search"
}
}
}
}Store Kagi API keys in .security.yml:
web:
kagi:
api_keys:
- "YOUR_KAGI_API_KEY"Kagi API usage may be billed or limited separately from a normal Kagi subscription, depending on your account and API setup.
| Config | Type | Default | Description |
|---|---|---|---|
enabled |
bool | false | Enable Tavily search |
api_key |
string | - | Tavily API key |
base_url |
string | - | Custom Tavily API base URL |
max_results |
int | 5 | Maximum number of results |
| Config | Type | Default | Description |
|---|---|---|---|
enabled |
bool | false | Enable SearXNG search |
base_url |
string | http://localhost:8888 |
SearXNG instance URL |
max_results |
int | 5 | Maximum number of results |
| Config | Type | Default | Description |
|---|---|---|---|
enabled |
bool | false | Enable GLM Search |
api_key |
string | - | GLM API key |
base_url |
string | https://open.bigmodel.cn/api/paas/v4/web_search |
GLM Search API URL |
search_engine |
string | search_std |
Search engine type |
max_results |
int | 5 | Maximum number of results |
| Config | Type | Default | Description |
|---|---|---|---|
prefer_native |
bool | true | Prefer provider's native search over configured search engines |
private_host_whitelist |
string[] | [] |
Private/internal hosts allowed for web fetching |
At runtime, the web_search tool accepts the following parameters:
| Field | Type | Required | Description |
|---|---|---|---|
query |
string | yes | Search query string |
count |
integer | no | Number of results to return. Default: 10, max: 10 |
range |
string | no | Optional time filter: d (day), w (week), m (month), y (year) |
If range is omitted, MintClaw performs an unrestricted search.
For Kagi, d, w, and m map to Kagi lens time_relative; y maps to a lens time_after date one year before the current day.
{
"query": "ai agent news",
"count": 10,
"range": "w"
}The image_generate tool creates image files through a provider that supports
image generation.
| Config | Type | Default | Description |
|---|---|---|---|
enabled |
bool | false | Enable the image generation tool |
model |
string | gpt-image-2 |
Image generation model. Values may include a provider prefix, for example openai-codex/gpt-image-2 |
tools.image_generate.model is configured independently from vision / load_image
routing. If it is not set, MintClaw uses gpt-image-2.
{
"tools": {
"image_generate": {
"enabled": true,
"model": "openai-codex/gpt-image-2"
}
}
}The apply_patch tool applies structured multi-file edits using the Codex patch
format. It is the preferred tool for targeted edits and changes spanning
multiple files.
| Config | Type | Default | Description |
|---|---|---|---|
tools.apply_patch.enabled |
bool | true |
Enable the apply_patch file-editing tool |
apply_patch uses the same workspace restriction and tools.allow_write_paths
rules as write_file and append_file.
| Field | Type | Required | Description |
|---|---|---|---|
input |
string | yes | Full patch text including *** Begin Patch and *** End Patch |
Supported operations:
*** Add File: path*** Update File: path*** Delete File: path
Example:
*** Begin Patch
*** Update File: app.go
@@
-fmt.Println("old")
+fmt.Println("new")
*** End Patch
The search_files tool searches workspace files without shelling out to
grep, rg, find, or ls. It is intended for routine repository and
workspace discovery while preserving MintClaw's read workspace restrictions and
tools.allow_read_paths. It respects .gitignore by default so normal search
does not drown in generated/cache/runtime files. This is a noise filter, not a
security boundary; use include_ignored: true only when explicitly inspecting
ignored environment, configuration, and runtime files.
| Config | Type | Default | Description |
|---|---|---|---|
tools.search_files.enabled |
bool | true |
Enable the search_files file-search tool |
| Field | Type | Required | Description |
|---|---|---|---|
pattern |
string | yes | Regex pattern for content search, or glob/name pattern for file search |
target |
string | no | content or files; default content |
path |
string | no | Directory or file to search; default . |
file_glob |
string | no | Restrict content search to matching file names, such as *.go |
output_mode |
string | no | content, files_only, or count; default content |
context |
int | no | Context lines around content matches; default 0, max 10 |
limit |
int | no | Maximum returned matches/files; default 100, max 500 |
include_ignored |
bool | no | Include .gitignored files and default noisy dirs such as node_modules; default false |
When results are incomplete because of a result count limit, byte limit, max
file size skip, or ignored-path exclusion, search_files appends a Search truncation block. The block includes truncated=true, the reason, returned
count, configured limit, total omitted result rows when known, reason-specific
sub-counts such as count_limit_omitted_count and rendered_omitted_count,
separate skipped counts for ignored or max-size files, and suggestions to narrow
by path, file_glob, or pattern. For ignored/runtime files, rerun with
include_ignored: true only when those files are explicitly needed.
Examples:
{"pattern": "NewAgentInstance", "path": "pkg", "file_glob": "*.go"}{"target": "files", "pattern": "*.md", "path": "docs"}{"pattern": "OPENAI_API_KEY", "path": ".", "file_glob": ".env*", "include_ignored": true}The exec tool is used to execute shell commands.
| Config | Type | Default | Description |
|---|---|---|---|
enabled |
bool | true | Enable the exec tool |
enable_deny_patterns |
bool | true | Enable default dangerous command blocking |
permission_mode |
string | "" | Optional mode. Use read_only to allow only commands classified as read-only |
custom_deny_patterns |
array | [] | Custom deny patterns (regular expressions) |
To completely disable the exec tool, set enabled to false:
Via config file:
{
"tools": {
"exec": {
"enabled": false
}
}
}Via environment variable:
MINTCLAW_TOOLS_EXEC_ENABLED=falseNote: When disabled, the agent will not be able to execute shell commands. This also affects the Cron tool's ability to run scheduled shell commands.
enable_deny_patterns: Set tofalseto completely disable the default dangerous command blocking patternspermission_mode: Set toread_onlyto block write, destructive, and unknown commands after deny/allow/path checks. Leave empty for the default behavior.custom_deny_patterns: Add custom deny regex patterns; commands matching these will be blocked
By default, MintClaw blocks the following dangerous commands:
- Delete commands:
rm -rf,del /f/q,rmdir /s - Disk operations:
format,mkfs,diskpart,dd if=, writing to/dev/sd* - System operations:
shutdown,reboot,poweroff - Command substitution:
$(),${}, backticks - Pipe to shell:
| sh,| bash - Privilege escalation:
sudo,chmod,chown - Process control:
pkill,killall,kill -9 - Remote operations:
curl | sh,wget | sh,ssh - Package management:
apt,yum,dnf,npm install -g,pip install --user - Containers:
docker run,docker exec - Git:
git push,git force - Other:
eval,source *.sh
The exec guard only validates the top-level command sent to MintClaw. It does not recursively inspect child processes spawned by build tools or scripts after that command starts running.
Examples of workflows that can bypass the direct command guard once the initial command is allowed:
make rungo run ./cmd/...cargo runnpm run build
This means the guard is useful for blocking obviously dangerous direct commands, but it is not a full sandbox for unreviewed build pipelines. If your threat model includes untrusted code in the workspace, use stronger isolation such as containers, VMs, or an approval flow around build-and-run commands.
{
"tools": {
"exec": {
"enable_deny_patterns": true,
"custom_deny_patterns": [
"\\brm\\s+-r\\b",
"\\bkillall\\s+python"
]
}
}
}The update_plan tool lets the agent publish structured progress for multi-step tasks. It mirrors OpenClaw's planning helper: the tool records the current ordered plan, validates step statuses, and returns the updated plan to the model without performing any external side effects.
| Config | Type | Default | Description |
|---|---|---|---|
tools.update_plan.enabled |
bool | false |
Register the agent-facing update_plan tool |
When update_plan is enabled, the tool description tells the model to use it only for non-trivial multi-step work, keep exactly one in_progress step while work is active, and avoid repeating the whole plan after each update.
| Field | Type | Required | Description |
|---|---|---|---|
explanation |
string | no | Short note explaining what changed in the plan |
plan |
array | yes | Ordered list of plan steps |
plan[].step |
string | yes | Short plan step |
plan[].status |
string | yes | One of pending, in_progress, or completed |
At most one step may be in_progress. The tool is intended for visible coordination during longer tasks; it does not run steps, schedule work, or replace workflow engines such as cron, MCP servers, or external orchestration.
{
"explanation": "Implementation has started.",
"plan": [
{ "step": "Inspect existing tools", "status": "completed" },
{ "step": "Add update_plan tool", "status": "in_progress" },
{ "step": "Run focused tests", "status": "pending" }
]
}The cron tool is used for scheduling periodic tasks.
| Config | Type | Default | Description |
|---|---|---|---|
enabled |
bool | true | Register the agent-facing cron tool |
allow_command |
bool | true | Allow command jobs without extra confirmation |
command_allowed_remotes |
string[] | [] | Remote channels or channel:chat_id values allowed for command jobs; * allows every channel and is dangerous unless all remote channels are trusted |
exec_timeout_minutes |
int | 5 | Execution timeout in minutes, 0 means no limit |
For schedule types, execution modes (deliver, agent turn, and command jobs), persistence, and the current command-security gates, see Scheduled Tasks and Cron Jobs.
The MCP tool enables integration with external Model Context Protocol servers.
If you prefer not to edit JSON manually, MintClaw also provides an MCP configuration manager CLI:
mintclaw mcp add— add or update a server (supports--deferred/--no-deferred)mintclaw mcp list— list all configured servers with status and deferred statemintclaw mcp show <name>— show full details and the tool list for one servermintclaw mcp test <name>— connectivity check for one servermintclaw mcp remove <name>— remove a server entrymintclaw mcp edit— openconfig.jsonin$EDITORfor advanced edits
These commands manage the same tools.mcp.servers section documented below. See MCP Server CLI for command syntax, examples, and behavior details.
When connecting to multiple MCP servers, exposing hundreds of tools simultaneously can exhaust the LLM's context window and increase API costs. The Discovery feature solves this by keeping MCP tools hidden by default.
Instead of loading all tools, the LLM is provided with a lightweight search tool (using BM25 keyword matching or Regex).
When the LLM needs a specific capability, it searches the hidden library. Matching tools are then temporarily "unlocked"
and injected into the context for a configured number of turns (ttl).
| Config | Type | Default | Description |
|---|---|---|---|
enabled |
bool | false | Enable MCP integration globally |
discovery |
object | {} |
Configuration for Tool Discovery (see below) |
servers |
object | {} |
Map of server name to server config |
| Config | Type | Default | Description |
|---|---|---|---|
enabled |
bool | false | Global default: if true, all MCP tools are hidden and loaded on-demand via search; if false, all tools are loaded into context. Individual servers can override this with the per-server deferred field. |
ttl |
int | 5 | Number of conversational turns a discovered tool remains unlocked |
max_search_results |
int | 5 | Maximum number of tools returned per search query |
use_bm25 |
bool | true | Enable the natural language/keyword search tool (tool_search_tool_bm25). Warning: consumes more resources than regex search |
use_regex |
bool | false | Enable the regex pattern search tool (tool_search_tool_regex) |
Note: If
discovery.enabledistrue, you MUST enable at least one search engine (use_bm25oruse_regex), otherwise the application will fail to start.
| Config | Type | Required | Description |
|---|---|---|---|
enabled |
bool | yes | Enable this MCP server |
deferred |
bool | no | Override deferred mode for this server only. true = tools are hidden and discoverable via search; false = tools are always visible in context. When omitted, the global discovery.enabled value applies. |
type |
string | no | Transport type: stdio, sse, http |
command |
string | stdio | Executable command for stdio transport |
args |
array | no | Command arguments for stdio transport |
env |
object | no | Environment variables for stdio process |
env_file |
string | no | Path to environment file for stdio process |
url |
string | sse/http | Endpoint URL for sse/http transport |
headers |
object | no | HTTP headers for sse/http transport |
session_loss_replay |
string | no | once (default) reconnects and invokes an interrupted call once; never reconnects for future calls but returns the interrupted call as uncertain without replay |
exclusive_lock_file |
string | no | Absolute path to an operator-owned, non-blocking exclusive lease for a stdio server; omitted by default |
- If
typeis omitted, transport is auto-detected:urlis set →ssecommandis set →stdio
httpandsseboth useurl+ optionalheaders.envandenv_fileare only applied tostdioservers.- Use
session_loss_replay: "never"for servers whose tools may have external effects that cannot be safely repeated after a lost response. - Use
exclusive_lock_filewhen a stdio server owns a persistent resource such as a browser profile. Its parent directory must already exist. MintClaw holds the OS lock across reconnects and releases it when the manager closes; remote HTTP/SSE servers reject this setting.
{
"tools": {
"mcp": {
"enabled": true,
"servers": {
"filesystem": {
"enabled": true,
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/tmp"
]
}
}
}
}
}{
"tools": {
"mcp": {
"enabled": true,
"servers": {
"remote-mcp": {
"enabled": true,
"type": "sse",
"url": "https://example.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_TOKEN"
}
}
}
}
}
}In this example, the LLM will only see the tool_search_tool_bm25. It will search and unlock Github or Postgres tools
dynamically only when requested by the user.
{
"tools": {
"mcp": {
"enabled": true,
"discovery": {
"enabled": true,
"ttl": 5,
"max_search_results": 5,
"use_bm25": true,
"use_regex": false
},
"servers": {
"github": {
"enabled": true,
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-github"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "YOUR_GITHUB_TOKEN"
}
},
"postgres": {
"enabled": true,
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-postgres",
"postgresql://user:password@localhost/dbname"
]
},
"slack": {
"enabled": true,
"type": "slack",
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-slack"
],
"env": {
"SLACK_BOT_TOKEN": "YOUR_SLACK_BOT_TOKEN",
"SLACK_TEAM_ID": "YOUR_SLACK_TEAM_ID"
}
}
}
}
}
}Discovery is enabled globally, but filesystem is pinned as always-visible while context7 follows the global
default (deferred). aws explicitly opts in to deferred mode even though it is the same as the global default.
{
"tools": {
"mcp": {
"enabled": true,
"discovery": {
"enabled": true,
"ttl": 5,
"max_search_results": 5,
"use_bm25": true
},
"servers": {
"filesystem": {
"enabled": true,
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"],
"deferred": false
},
"context7": {
"enabled": true,
"command": "npx",
"args": ["-y", "@upstash/context7-mcp"]
},
"aws": {
"enabled": true,
"command": "npx",
"args": ["-y", "aws-mcp-server"],
"deferred": true
},
"inventorydb": {
"enabled": true,
"command": "/path/to/inventorydb-mcp",
"deferred": true,
"visible_tools": [
"mcp_inventorydb_shopping_add_item",
"mcp_inventorydb_shopping_list_items",
"mcp_inventorydb_shopping_update_items"
]
}
}
}
}
}Tip:
deferredon a per-server basis is independent ofdiscovery.enabled. You can keepdiscovery.enabled: falseglobally (all tools visible by default) and still mark individual high-volume servers as"deferred": trueto avoid polluting the context with their tools.When a server stays deferred,
visible_toolscan keep a small allowlist of directly visible MCP tools while all other tools from that server remain hidden behind discovery.
The skills tool configures skill discovery and installation via registries like ClawHub and GitHub.
| Config | Type | Default | Description |
|---|---|---|---|
registries.clawhub.enabled |
bool | true | Enable ClawHub registry |
registries.clawhub.base_url |
string | https://clawhub.ai |
ClawHub base URL |
registries.clawhub.auth_token |
string | "" |
Optional Bearer token for higher rate limits |
registries.clawhub.search_path |
string | "" |
Search API path |
registries.clawhub.skills_path |
string | "" |
Skills API path |
registries.clawhub.download_path |
string | "" |
Download API path |
registries.clawhub.timeout |
int | 0 | Request timeout in seconds (0 = default) |
registries.clawhub.max_zip_size |
int | 0 | Max skill zip size in bytes (0 = default) |
registries.clawhub.max_response_size |
int | 0 | Max API response size in bytes (0 = default) |
registries.github.enabled |
bool | true | Enable GitHub installs via registry config |
registries.github.base_url |
string | https://github.com |
GitHub or GitHub Enterprise base URL |
registries.github.auth_token |
string | "" |
GitHub personal access token |
registries.github.proxy |
string | "" |
HTTP proxy for GitHub API requests |
github.* is deprecated. Use registries.github.* instead. The legacy fields are still supported for compatibility and will be removed later.
| Config | Type | Default | Description |
|---|---|---|---|
github.base_url |
string | https://github.com |
Deprecated GitHub base URL |
github.proxy |
string | "" |
Deprecated GitHub proxy |
github.token |
string | "" |
Deprecated GitHub token |
| Config | Type | Default | Description |
|---|---|---|---|
max_concurrent_searches |
int | 2 | Max concurrent skill search requests |
search_cache.max_size |
int | 50 | Max cached search results |
search_cache.ttl_seconds |
int | 300 | Cache TTL in seconds |
{
"tools": {
"skills": {
"registries": {
"clawhub": {
"enabled": true,
"base_url": "https://clawhub.ai",
"auth_token": "",
"search_path": "",
"skills_path": "",
"download_path": "",
"timeout": 0,
"max_zip_size": 0,
"max_response_size": 0
},
"github": {
"enabled": true,
"base_url": "https://github.com",
"auth_token": "",
"proxy": ""
}
},
"github": {
"base_url": "https://github.com",
"proxy": "",
"token": ""
},
"max_concurrent_searches": 2,
"search_cache": {
"max_size": 50,
"ttl_seconds": 300
}
}
}
}All configuration options can be overridden via environment variables with the format MINTCLAW_TOOLS_<SECTION>_<KEY>:
For example:
MINTCLAW_TOOLS_WEB_BRAVE_ENABLED=trueMINTCLAW_TOOLS_EXEC_ENABLED=falseMINTCLAW_TOOLS_EXEC_ENABLE_DENY_PATTERNS=falseMINTCLAW_TOOLS_CRON_EXEC_TIMEOUT_MINUTES=10MINTCLAW_TOOLS_MCP_ENABLED=trueMINTCLAW_TOOLS_MCP_MAX_INLINE_TEXT_CHARS=16384
Note: Nested map-style config (for example tools.mcp.servers.<name>.*) is configured in config.json rather than
environment variables.
For MCP tools, tools.mcp.max_inline_text_chars controls how much text result is kept inline in model context. The threshold is counted in Unicode characters (Go runes), not bytes. For example, 16384 means up to 16,384 characters inline, which may occupy more than 16 KB for multibyte text such as CJK. Above this threshold, MintClaw saves the MCP text result as a local artifact in the agent workspace and gives the model a short note plus a structured [file:...] artifact path instead of injecting the full payload into context. The artifact is registered in MediaStore as text/plain with delete-on-cleanup ownership, so tools.media_cleanup TTL cleanup removes the exact managed file. If registration fails, MintClaw deletes the new file and returns only a bounded omission note.
tools.media_cleanup.max_age_minutes controls how long media:// references and their managed files remain available. The default is 10,080 minutes (7 days). Inbound files downloaded into MintClaw's temporary media directory are promoted into the workspace's persistent state/media/files directory before registration, so their references survive gateway restarts and host reboots until the retention window expires. Historical images are represented in prompts by lightweight path tags rather than being reattached as base64; the agent can explicitly open them with load_image when the user refers back to an earlier image.