May 01, 2026

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 JSON

Token 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:

  1. Workspace File Loading: All files from `.openclaw/` (AGENTS.md, SOUL.md, USER.md, TOOLS.md, SKILLS.md) are loaded unconditionally
  2. Tool List Compilation: The complete tool registry is serialized into the system prompt
  3. Skill Descriptions Injection: All skill manifests are embedded verbatim
  4. 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-model

Compare 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: false

Downstream Effects

  1. Token Drain: Every model receives ~6,000-20,000 tokens of context it cannot use
  2. Hallucination Triggers: Models trained without tool-calling see tool syntax in context and attempt to emulate it
  3. Role Bleed: Orchestrator context leaks into conversational models, causing behavioral drift
  4. 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-turbo

After (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: false

Phase 2: Field Definitions

FieldTypeDefaultDescription
workspaceFilesstring[]All filesList of workspace files to inject. Files not listed are excluded.
toolsbooleantrueInclude full tool list in system prompt
skillsbooleantrueInclude 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: 1

Verification 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 response

Verification 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: true

Pitfall 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 role

Pitfall 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 list

Pitfall 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
  • 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
  • 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

Evidence & Sources

This troubleshooting guide was automatically synthesized by the FixClaw Intelligence Pipeline from community discussions.