Troubleshooting
unknown capability or unknown tool policy selector
Policy selectors are strict.
Correct:
filesystem.read
filesystem/read_text_fileIncorrect examples:
filesystem-read
filesystem.read_text_file
filesystem/read-fileUse a capability from the capability table or an exact server/tool ID.
Subagent appears in the catalog but has no tools
This is expected when allow_tools is empty.
Declaring:
[mcp_servers.filesystem]
...does not grant access. Add an explicit policy:
allow_tools = ["filesystem/*"]child tool selector references unknown MCP server
The part before / must exactly match a key under [mcp_servers.<name>].
This must match:
allow_tools = ["repo/*"]
[mcp_servers.repo]
...child tool selector references unavailable tool
An exact selector points to a tool that the child did not advertise.
Check both:
- the exact child tool name;
- whether the child process's own
--allow/--denypolicy disabled it.
Agent reports missing environment variable
OPENROUTER_API_KEY is the default credential variable for model_provider = "openrouter", so it must exist in the environment of the tuls agents process.
Check before launching the MCP client/process:
printenv OPENROUTER_API_KEYFor GUI MCP clients, configure secrets using that client's environment/secret mechanism rather than assuming the GUI inherited your terminal session.
OpenRouter returns an HTTP error
openrouter is first-class: the request goes to https://openrouter.ai/api/v1/responses with Bearer auth and the credential from OPENROUTER_API_KEY. Overrides are rejected, so a custom-style base_url/env_key/wire_api in the agent file is a configuration error.
Verify that OPENROUTER_API_KEY is set in the tuls agents process and that the selected OpenRouter model supports the behavior needed by the agent, especially tool calling and any requested reasoning parameters.
Custom provider returns an error at /responses
wire_api = "responses" requires a Responses-compatible endpoint, not merely an OpenAI Chat Completions-compatible endpoint.
Child MCP cannot see an environment variable
stdio child MCP processes deliberately start with a minimal environment. Pass required variables explicitly:
env = { TOKEN = "${TOKEN}" }shell command works in a terminal but not through tuls
Remember:
programis an executable name;argsare separate argv entries;- no shell syntax is interpreted unless you explicitly run a shell;
- spawned processes use a reduced environment.
For example, use:
{
"program": "cargo",
"args": ["test"]
}not:
{
"program": "cargo test"
}Relative paths resolve somewhere unexpected
For filesystem and shell, relative paths resolve against the first root:
tuls filesystem /work/project /work/sharedHere src/main.rs resolves relative to /work/project.
Fetch cannot access localhost/private services
That is the default --network public policy.
For an explicitly trusted deployment that needs private network access:
tuls fetch \
--network unrestricted \
--allow network.fetchTreat unrestricted network access as a meaningful privilege increase.