Per-Model Context Profiles for Workspace Injection and Tool Visibility
Control which workspace files, tools, and skills are injected per model alias to prevent context bloat, tool hallucinations, and wasted tokens on models without tool-calling capabilities.
π Symptoms
Context Bloat on Non-Tool-Capable Models
When routing to models through external proxies or OpenAI-compatible endpoints that lack tool-calling support, the system prompt still includes the full tool list:
--- System Prompt Excerpt ---
...
## Available Tools
You have access to the following tools. Each tool invocation must be formatted as:
function_calls
[{"name": "bash", "arguments": {"command": "ls -la"}}]
[/OL]
function_calls
[{"name": "read_file", "arguments": {"path": "config.yaml"}}]
[/OL]
...
### Tool Descriptions (truncated for display)
**bash**: Executes shell commands in a sandboxed environment...
**read_file**: Reads contents of a file from the workspace...
**write_file**: Writes content to a file at the specified path...
Tool Hallucination Errors
Models without tool-calling infrastructure emit malformed function-call syntax:
Error: Failed to parse model response as valid tool calls
Raw output: "I'll run that command for you. function_calls\n[{"name": "bash"...`
Model 'research-model' via 'custom-proxy' produced unsupported function call format.
Expected: OpenAI tool_call format
Received: Inline text with malformed JSONToken Waste Indicators
System prompt size exceeds reasonable limits for the target model’s context window:
$ openclaw analyze-prompt-size --model research
Warning: Estimated system prompt size: 18,420 tokens
Model 'research-model' context window: 8,192 tokens
Workspace files injected: AGENTS.md, SOUL.md, USER.md, TOOLS.md, SKILLS.md
Tools injected: 12 tools (4,280 tokens)
Skills injected: 5 skills (2,150 tokens)
Effective working memory: -8,428 tokens (OVERFLOW)Multi-Model Behavioral Contamination
Switching models via /model research retains full orchestrator context inappropriate for the research role:
User: /model research
> Now using model: research via custom-proxy
User: What's the weather in Tokyo?
Assistant: I'll check that for you using the weather tool.
function_calls
[{"name": "get_weather", "arguments": {"location": "Tokyo"}}]
[/OL]
Error: Tool 'get_weather' is not available for model 'research'.
Available capabilities: conversation onlyπ§ Root Cause
Uniform Context Injection Architecture
OpenClaw’s current context injection pipeline applies identical processing to all model invocations regardless of the target model’s capabilities or configured role. The injection pipeline follows this sequence:
- Workspace File Loading: All files from `.openclaw/` (AGENTS.md, SOUL.md, USER.md, TOOLS.md, SKILLS.md) are loaded unconditionally
- Tool List Compilation: The complete tool registry is serialized into the system prompt
- Skill Descriptions Injection: All skill manifests are embedded verbatim
- Runtime Instruction Appending: Model-agnostic operational instructions are appended
Architectural Limitations
The issue stems from two architectural constraints:
1. Provider-Level Capability Detection Gap
The current implementation lacks capability introspection at the provider/alias level:
// Current: Context injection happens without checking model capabilities
class ContextInjector {
inject(prompt: Prompt, model: Model): Prompt {
return {
system: [
...this.loadWorkspaceFiles(), // Always loads ALL files
...this.buildToolList(), // Always includes ALL tools
...this.buildSkillList(), // Always includes ALL skills
...prompt.system
]
};
}
}2. Alias-to-Profile Mapping Absence
Model aliases do not carry metadata about intended role or capability requirements. The configuration schema only captures:
models:
aliases:
research: # No capability metadata attached
provider: custom-proxy
model: research-modelCompare to the required schema with contextProfile:
models:
aliases:
research:
provider: custom-proxy
model: research-model
contextProfile: # Missing field causes uniform injection
workspaceFiles: ["USER.md"]
tools: false
skills: falseDownstream Effects
- Token Drain: Every model receives ~6,000-20,000 tokens of context it cannot use
- Hallucination Triggers: Models trained without tool-calling see tool syntax in context and attempt to emulate it
- Role Bleed: Orchestrator context leaks into conversational models, causing behavioral drift
- Cost Inflation: API costs increase proportionally with token count per request
π οΈ Step-by-Step Fix
Phase 1: Update Configuration Schema
Add contextProfile blocks to model aliases requiring customized context injection.
Before (Uniform Injection)
# ~/.openclaw/config.yaml
models:
aliases:
orchestrator:
provider: openai
model: gpt-4-turbo
research:
provider: custom-proxy
model: research-model
coding:
provider: anthropic
model: claude-3-sonnet
chat:
provider: openai
model: gpt-3.5-turboAfter (Profile-Based Injection)
# ~/.openclaw/config.yaml
models:
aliases:
orchestrator:
provider: openai
model: gpt-4-turbo
contextProfile:
workspaceFiles: ["AGENTS.md", "SOUL.md", "USER.md", "TOOLS.md", "SKILLS.md"]
tools: true
skills: true
research:
provider: custom-proxy
model: research-model
contextProfile:
workspaceFiles: ["USER.md"]
tools: false
skills: false
coding:
provider: anthropic
model: claude-3-sonnet
contextProfile:
workspaceFiles: ["AGENTS.md", "USER.md", "TOOLS.md"]
tools: true
skills: true
chat:
provider: openai
model: gpt-3.5-turbo
contextProfile:
workspaceFiles: ["USER.md"]
tools: false
skills: falsePhase 2: Field Definitions
| Field | Type | Default | Description |
|---|---|---|---|
workspaceFiles | string[] | All files | List of workspace files to inject. Files not listed are excluded. |
tools | boolean | true | Include full tool list in system prompt |
skills | boolean | true | Include skill descriptions in system prompt |
Phase 3: Validate Configuration
$ openclaw config validate
β Configuration schema valid
β 4 model aliases configured
β 2 context profiles active (orchestrator, coding)
β 2 minimal profiles active (research, chat)
β No conflicting workspace files referenced
Profile breakdown:
orchestrator: 5 files, tools=true, skills=true (full injection)
research: 1 file, tools=false, skills=false (minimal)
coding: 3 files, tools=true, skills=true (partial)
chat: 1 file, tools=false, skills=false (minimal)Phase 4: Migrate Existing Conditional Logic
If you previously used conditional blocks in workspace files, remove them and rely on contextProfile instead.
Before (Fragile Conditional Blocks in AGENTS.md)
## Tool Usage Guidelines
When operating as the **orchestrator** model, use tools freely:
- `bash` for system operations
- `read_file` for file inspection
- `write_file` for file creation
### If you are the **research** model, IGNORE the tool section above.
You do not have tool access. Respond conversationally only.
### If you are the **chat** model, IGNORE all tool references.
...After (Clean AGENTS.md Without Conditionals)
## Orchestration Guidelines
When operating as the orchestrator, coordinate tool usage:
- Use `bash` for system operations
- Use `read_file` for file inspection
- Delegate subtasks to specialized models as needed
## Collaboration Protocol
Models without tool access should communicate findings conversationally.
...π§ͺ Verification
Verification 1: Confirm Context Profile Application
$ openclaw debug context --model research --message "Hello"
=== Context Injection for 'research' ===
Provider: custom-proxy
Model: research-model
Context Profile: {workspaceFiles: ["USER.md"], tools: false, skills: false}
Workspace Files (1):
β USER.md (loaded, 245 tokens)
Tools (0):
β Excluded by contextProfile
Skills (0):
β Excluded by contextProfile
Estimated System Prompt: 312 tokens
---Verification 2: Compare Token Counts Across Models
$ openclaw analyze-prompt-size --all-models
Model | Context Profile | Files | Tools | Skills | Est. Tokens
---------------|-----------------------|-------|-------|--------|-------------
orchestrator | full | 5 | 12 | 5 | 18,420
research | minimal | 1 | 0 | 0 | 312
coding | partial | 3 | 8 | 3 | 8,150
chat | minimal | 1 | 0 | 0 | 298
Total potential savings: 35,688 tokens across all models
Savings per request (research/chat): ~18,000 tokens (98% reduction)Verification 3: Test Tool Rejection on Restricted Models
$ openclaw model research --prompt "Use the bash tool to list files"
[research via custom-proxy]
Error: Tool injection disabled for model 'research'
contextProfile.tools = false
This model does not support tool calls.
Hint: Switch to 'orchestrator' for tool-enabled operations.
Exit code: 1Verification 4: Validate No Tool Hallucinations
$ openclaw model research --prompt "Run ls -la for me"
[research via custom-proxy]
> I don't have the ability to execute commands directly. I can help you
> understand command outputs if you share them, or explain what `ls -la`
> does.
β No tool hallucinations detected
β Response format: conversation (expected)
β No function_call syntax in responseVerification 5: Confirm Workspace File Isolation
$ openclaw debug context --model research --show-loaded-files
=== Loaded Workspace Files for 'research' ===
β USER.md (245 tokens)
β AGENTS.md (excluded)
β SOUL.md (excluded)
β TOOLS.md (excluded)
β SKILLS.md (excluded)
$ openclaw debug context --model orchestrator --show-loaded-files
=== Loaded Workspace Files for 'orchestrator' ===
β AGENTS.md (1,204 tokens)
β SOUL.md (892 tokens)
β USER.md (245 tokens)
β TOOLS.md (4,280 tokens)
β SKILLS.md (2,150 tokens)β οΈ Common Pitfalls
Pitfall 1: Omitting Required Workspace Files
When specifying workspaceFiles, ensure critical operational files are included.
# INCORRECT: Excludes essential AGENTS.md with orchestrator instructions
models:
aliases:
orchestrator:
provider: openai
model: gpt-4-turbo
contextProfile:
workspaceFiles: ["USER.md", "TOOLS.md"] # Missing AGENTS.md
tools: true
skills: true
# CORRECT: Include all required files
models:
aliases:
orchestrator:
provider: openai
model: gpt-4-turbo
contextProfile:
workspaceFiles: ["AGENTS.md", "USER.md", "TOOLS.md"] # AGENTS.md present
tools: true
skills: truePitfall 2: Conflicting Profiles on Shared Models
The same underlying model can have different profiles via aliases, but this can cause confusion.
# PROBLEMATIC: Same model, different profiles
models:
aliases:
research:
provider: custom-proxy
model: shared-model
contextProfile:
workspaceFiles: ["USER.md"]
tools: false
orchestrator:
provider: custom-proxy
model: shared-model
contextProfile:
workspaceFiles: ["AGENTS.md", "SOUL.md", "USER.md", "TOOLS.md"]
tools: true
# BEHAVIOR: Switching via /model changes injection profile
# RISK: Users may not realize they're getting different context
# MITIGATION: Use clearly distinct alias names indicating rolePitfall 3: Non-Existent Workspace File References
Referencing files not present in .openclaw/ results in silent exclusion (no error), but wastes configuration space.
# File does not exist, will be silently ignored
models:
aliases:
research:
contextProfile:
workspaceFiles: ["USER.md", "RESEARCH_GUIDE.md"] # RESEARCH_GUIDE.md missing
$ openclaw config validate
Warning: Workspace file 'RESEARCH_GUIDE.md' not found in .openclaw/
Hint: Create the file or remove from workspaceFiles listPitfall 4: Backward Compatibility Oversight
Models without contextProfile retain full injection behavior. This is intentional for backward compatibility, but teams may expect uniform behavior.
# Legacy alias without contextProfile retains full injection
models:
aliases:
legacy-model:
provider: openai
model: gpt-3.5-turbo
# No contextProfile = injects everything (legacy behavior)
# VERIFY: Check actual injection behavior
$ openclaw debug context --model legacy-model | grep "Context Profile"
Context Profile: undefined (using defaults)Pitfall 5: Docker/Container Environment Path Issues
In Docker deployments, workspace file paths resolve relative to the container’s working directory, not the host.
# Host: Files at ~/.openclaw/
# Container: Files at /app/.openclaw/
# INCORRECT: Path in container doesn't match host
$ docker run openclaw debug context --model research
Error: Workspace file 'USER.md' not found in /app/.openclaw/
# CORRECT: Mount volume to align paths
$ docker run -v ~/.openclaw:/app/.openclaw openclaw debug context --model research
β USER.md loaded (245 tokens)Pitfall 6: Proxy-Provided Models with Hidden Tool Support
Some OpenAI-compatible proxies claim tool support but fail at runtime. The contextProfile prevents injection, but verify proxy capabilities first.
# Verify actual proxy capabilities before disabling tools
$ curl -X POST https://proxy.example.com/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "research-model", "messages": [{"role": "user", "content": "test"}], "tools": [{"type": "function", "function": {"name": "test", "parameters": {"type": "object"}}}]}'
# If returns 200 with tool call support, keep tools: true
# If returns 400 or ignores tools, set tools: falseπ Related Errors
Error Codes and Related Issues
TOOL_CALL_UNSUPPORTED: Model attempted tool invocation but the provider does not support tool-calling format. Often occurs when tools are injected to non-compatible models.CONTEXT_EXCEEDS_WINDOW: Combined system prompt exceeds model's context window. Caused by injecting all workspace files and tools to models with limited context.MALFORMED_FUNCTION_CALL: Model emitted tool-call syntax without proper JSON formatting. Common when models without tool infrastructure receive tool descriptions.WORKSPACE_FILE_NOT_FOUND: Referenced workspace file does not exist in `.openclaw/`. Occurs when contextProfile references missing files.PROFILE_OVERRIDE_CONFLICT: Same underlying model has conflicting contextProfile settings across aliases.- Issue #142: Request for per-model system prompt customization
- Issue #203: Tool descriptions causing hallucinations on non-tool models
- Issue #311: Context window exhaustion with multi-tool injection
- Issue #445: Multi-provider proxy tool compatibility detection
- Issue #512: Feature request: contextProfile for workspace file control
Related Configuration Topics
- Model Aliases:
models.aliases.*configuration block - Provider Configuration:
models.providers.*for endpoint and credential setup - Workspace Files: Files in
.openclaw/directory - Tool Registry:
tools.*for tool definition and registration - Skill Manifests:
skills.*for skill description files