openclaw - 💡(How to fix) Fix feat: Per-request workspace override via HTTP header (x-openclaw-workspace) [2 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#51451Fetched 2026-04-08 01:11:07
View on GitHub
Comments
2
Participants
2
Timeline
2
Reactions
0
Author
Participants
Timeline (top)
commented ×2

Add support for a per-request workspace override via an HTTP header (x-openclaw-workspace) on the /v1/chat/completions endpoint.


Root Cause

Add support for a per-request workspace override via an HTTP header (x-openclaw-workspace) on the /v1/chat/completions endpoint.


Code Example

x-openclaw-workspace: /path/to/tenant/workspace

---

curl -X POST http://openclaw-host:18789/v1/chat/completions \
  -H "Authorization: Bearer TOKEN" \
  -H "x-openclaw-workspace: /efs/tenants/tenant_001" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openclaw:main",
    "messages": [{"role": "user", "content": "Analyze my sales data"}]
  }'

---

export function resolveWorkspaceOverride(req: IncomingMessage): string | undefined {
  const raw = getHeader(req, "x-openclaw-workspace")?.trim();
  return raw || undefined;
}

---

const workspaceOverride = resolveWorkspaceOverride(req);
// pass workspaceOverride into buildAgentCommandInput → agentCommand

---

if (opts.workspaceOverride) {
  workspaceDir = opts.workspaceOverride;
}
RAW_BUFFERClick to expand / collapse

🚀 Feature Request

Summary

Add support for a per-request workspace override via an HTTP header (x-openclaw-workspace) on the /v1/chat/completions endpoint.


Problem / Motivation

When deploying OpenClaw as a multi-tenant SaaS backend (e.g., serving thousands of merchants/users from a shared cluster), each tenant needs isolated memory, workspace files, and context — but the current architecture only supports a static workspace path configured per agent in openclaw.json.

This forces one of two unacceptable tradeoffs:

  1. One OC instance per tenant — prohibitively expensive at scale (10k+ tenants × N instances each)
  2. Shared workspace for all tenants — breaks memory isolation entirely

There is no way today to tell OpenClaw "for this specific request, use workspace /efs/tenants/tenant_001" without modifying agent config and restarting.


Proposed Solution

Support a new HTTP header on /v1/chat/completions:

x-openclaw-workspace: /path/to/tenant/workspace

When this header is present, OpenClaw uses the specified path as the workspace for that request only — overriding the agent's configured workspaceDir for the duration of the run.

This allows the router layer (sitting in front of the OC cluster) to:

  1. Map tenant_id → workspace path (e.g., on EFS/NFS)
  2. Inject the path via header on each request
  3. Let OC handle memory reads/writes in the correct isolated directory

Example Usage

curl -X POST http://openclaw-host:18789/v1/chat/completions \
  -H "Authorization: Bearer TOKEN" \
  -H "x-openclaw-workspace: /efs/tenants/tenant_001" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openclaw:main",
    "messages": [{"role": "user", "content": "Analyze my sales data"}]
  }'

Implementation Sketch

The change is minimal (~15 lines across 2 files):

src/gateway/http-utils.ts — add header resolver:

export function resolveWorkspaceOverride(req: IncomingMessage): string | undefined {
  const raw = getHeader(req, "x-openclaw-workspace")?.trim();
  return raw || undefined;
}

src/gateway/openai-http.ts — read header and pass to agentCommand:

const workspaceOverride = resolveWorkspaceOverride(req);
// pass workspaceOverride into buildAgentCommandInput → agentCommand

src/commands/agent.ts — apply override in workspace resolution:

if (opts.workspaceOverride) {
  workspaceDir = opts.workspaceOverride;
}

Security Considerations

  • The path should be validated (must be absolute, no path traversal ../)
  • Should only be accepted when gateway auth is satisfied (already enforced by existing auth middleware)
  • Optionally: add a config flag gateway.http.allowWorkspaceOverride: true to require explicit opt-in

Use Cases

ScenarioBenefit
Multi-tenant SaaS (merchants, users)Per-tenant memory isolation
Enterprise multi-department deploymentDepartment-scoped context
CI/CD pipelinesPer-PR isolated workspace
TestingReproducible workspace state per test run

Alternatives Considered

  • One agent config per tenant in openclaw.json: Doesn't scale beyond hundreds of agents; hot-reload performance degrades
  • Router injects full memory as system prompt: Works but loses OC's native memory_search/memory_get tooling and file write-back

I'm willing to contribute a PR for this. Happy to discuss the implementation approach before coding.

extent analysis

Fix Plan

To implement the per-request workspace override, follow these steps:

  • Add a header resolver function in src/gateway/http-utils.ts:
export function resolveWorkspaceOverride(req: IncomingMessage): string | undefined {
  const raw = getHeader(req, "x-openclaw-workspace")?.trim();
  return raw || undefined;
}
  • Read the header and pass it to buildAgentCommandInput in src/gateway/openai-http.ts:
const workspaceOverride = resolveWorkspaceOverride(req);
// pass workspaceOverride into buildAgentCommandInput → agentCommand
  • Apply the override in workspace resolution in src/commands/agent.ts:
if (opts.workspaceOverride) {
  workspaceDir = opts.workspaceOverride;
}
  • Validate the workspace path to prevent path traversal attacks:
if (opts.workspaceOverride) {
  const path = require('path');
  if (!path.isAbsolute(opts.workspaceOverride)) {
    throw new Error('Workspace path must be absolute');
  }
  if (opts.workspaceOverride.includes('../')) {
    throw new Error('Path traversal detected');
  }
  workspaceDir = opts.workspaceOverride;
}
  • Add a config flag gateway.http.allowWorkspaceOverride to require explicit opt-in:
if (config.gateway.http.allowWorkspaceOverride !== true) {
  throw new Error('Workspace override is not allowed');
}

Verification

To verify the fix, test the following scenarios:

  • Send a request with the x-openclaw-workspace header and verify that the workspace is overridden correctly.
  • Send a request without the x-openclaw-workspace header and verify that the default workspace is used.
  • Test with invalid workspace paths (e.g., relative paths, paths with traversal attacks) and verify that errors are thrown.

Extra Tips

  • Make sure to handle errors and exceptions properly when working with file systems and network requests.
  • Consider adding additional logging and monitoring to track workspace overrides and potential security issues.
  • Review the implementation for any potential performance impacts, especially when dealing with a large number of requests and tenants.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING