#Multiple agents with shared project

1 messages · Page 1 of 1 (latest)

weary abyss
#

How to set up Multiple agents with shared project ?

Eg. All agents have their own directory, each contain md files. But all works are in Projects folder
.
└── workspaces/
├── FrontEndDev
├── BackEndDev
├── DevOps
└── Projects (Folder)

indigo girderBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> âś… Mark Solution

vast geodeBOT
#

You basically want each agent to have its own workspace (AGENTS.md/SOUL.md/etc), but still have one shared “real code” folder that all agents can read/write.

Key detail from the docs: an agent workspace is the default cwd, not a hard sandbox — relative paths resolve inside the workspace, but absolute paths can reach elsewhere unless you’ve enabled sandboxing / tools.fs.workspaceOnly.
Docs: https://docs.openclaw.ai/concepts/agent-workspace

1) Create multiple agents (separate workspaces)

Use multi-agent mode and give each agent its own workspace directory.

Docs: https://docs.openclaw.ai/concepts/multi-agent

Example ~/.openclaw/openclaw.json (JSON5):

{
  agents: {
    list: [
#
      { id: "frontend", workspace: "~/workspaces/FrontEndDev" },
      { id: "backend",  workspace: "~/workspaces/BackEndDev" },
      { id: "devops",   workspace: "~/workspaces/DevOps" },
    ],
  },
}

(You can also use openclaw agents add <id> which scaffolds a proper workspace.)

2) Make the shared Projects/ folder visible inside each workspace (recommended)

This is the cleanest way because it keeps paths “workspace-local”, so it works even with stricter security settings.

Your layout:

#
workspaces/
  FrontEndDev/
  BackEndDev/
  DevOps/
  Projects/        <-- shared

Add a symlink inside each agent workspace:

  • workspaces/FrontEndDev/Projects -> ../Projects
  • workspaces/BackEndDev/Projects -> ../Projects
  • workspaces/DevOps/Projects -> ../Projects

Then every agent can just use paths like:

  • Projects/my-app/...
#

…and it stays consistent across agents.

3) If you have sandboxing enabled: use bind mounts (instead of symlinks)

With sandboxing, tools run in Docker and won’t automatically see host paths. You need binds.

Docs: https://docs.openclaw.ai/gateway/sandboxing

Typical pattern: bind the host projects folder into the sandbox workspace so it appears as Projects/:

{
  agents: {
    defaults: {
      sandbox: {
        mode: "non-main",
        workspaceAccess: "rw",
#
        docker: {
          binds: [
            "/home/you/workspaces/Projects:/workspace/Projects:rw"
          ],
        },
      },
    },
  },
}

Quick sanity check question

Do you currently have either of these turned on?

  • tools.fs.workspaceOnly: true (security hardening), or
  • agents.defaults.sandbox.mode not "off" (sandboxing)
#

If yes, symlink/bind-into-workspace is the way. If not, you can also just use ../Projects, but you’ll eventually trip on workspace-only restrictions.

weary abyss
#

So basically, symlink is the only way ? Then how do i scale ? if i decided to add more agents into the team or even create department say the above is Dev team, I add MKT team later.

vast geodeBOT
#

Symlink is the most common way, but it’s not the only way.

What you’re really trying to achieve is: “make Projects/ appear inside each agent’s workspace”, so the agent can use nice relative paths like Projects/foo and (optionally) you can keep stricter settings like sandboxing / tools.fs.workspaceOnly.

Options (in practice)

Option A (recommended, simplest): symlink Projects/ into each workspace

For each new agent workspace, create a link:

  • FrontEndDev/Projects -> ../Projects
  • BackEndDev/Projects -> ../Projects
  • etc.

This scales fine in real life because you don’t do it manually forever—you standardize it.

How to scale it cleanly:

  • Put shared stuff under a single “shared” folder:
#
  workspaces/
    shared/
      Projects/
    FrontEndDev/
      Projects -> ../shared/Projects
    BackEndDev/
      Projects -> ../shared/Projects
    DevOps/
      Projects -> ../shared/Projects
  • When you add a new agent (or a new department like MKT), you create the workspace folder and add the same symlink. Most people automate that with a tiny script / make target.

Option B (best if you use sandboxing): Docker bind mount the shared folder

If you have agents.defaults.sandbox enabled, symlinks may not help (tools run in a container). In that case you bind-mount the host Projects folder into the sandbox workspace once, globally:

Docs: https://docs.openclaw.ai/gateway/sandboxing

#

Example idea:

  • bind .../Projects → /workspace/Projects (rw or ro)

This scales better than symlinks because new agents inherit the same binds via agents.defaults.sandbox.docker.binds.

Option C (least strict): just use absolute paths to the shared folder

This only works reliably if you don’t enforce workspace-only restrictions and you’re not sandboxing. It’s convenient, but you’ll usually end up tightening security later and then it breaks.

Docs context: workspace is cwd, not a hard sandbox
https://docs.openclaw.ai/concepts/agent-workspace

“Adding more agents / new departments” strategy

Think in “shared resources” + “agent workspaces”:

  • Shared code: workspaces/shared/Projects
  • Shared MKT assets: workspaces/shared/MKT
  • Each agent workspace links (or bind-mounts) only what it needs:
#
  • Dev agents get Projects
    • MKT agents get MKT (and maybe read-only access to Projects if desired)

If you tell me whether you’re running with sandboxing on (and/or tools.fs.workspaceOnly: true), I can point you to the cleanest config pattern for your setup (symlink-only vs bind-mount defaults, and rw vs ro per agent).

wooden elm
# vast geode ``` workspaces/ shared/ Projects/ FrontEndDev/ Projects ->...

whenever i try to bind mount inside the sandbox container i get an error "Sandbox security" error, stating that the bind mount for /home/node/.openclaw/workspace/projects is targeting a reserved container path within its environment." i have tried everything to bypass but i am out of ideas. it allows a bind mount of /home/node/.openclaw/workspace/projects:/home/node/.openclaw/workspace/projects but then the subagent can never find the files because they are not technically in the workspace

vast geodeBOT
#

That error is expected: OpenClaw blocks Docker binds whose container target lands on “reserved” paths (not just the exact path, but under it too), because it can shadow OpenClaw’s own mounts (workspace/agent mounts, media, etc.).

Two key gotchas in what you tried:

  1. Inside the tool sandbox container, the workspace is typically /workspace (not ~/.openclaw/workspace/...), unless you changed agents.defaults.sandbox.docker.workdir.
  2. If you have tools.fs.workspaceOnly: true, then read/write/edit will only work inside the workspace, so mounting your project at some random container path won’t be usable via fs tools.

Option A (recommended): don’t share a single working tree

Give each agent its own clone/worktree of the repo under its own workspace. This avoids agents stomping on the same files and makes conflicts tractable (git branches/PRs). It’s the most reliable “multi-agent coding” setup.

Option B (works, safest config): mount outside workspace + disable fs workspaceOnly

Mount your shared Projects folder somewhere not reserved, e.g. /projects, and make sure you don’t have tools.fs.workspaceOnly: true (or turn it off for the agents that need it).

{
  tools: { fs: { workspaceOnly: false } },
#
  agents: {
    defaults: {
      sandbox: {
        mode: "all",
        workspaceAccess: "rw",
        docker: {
          binds: [
            "/home/node/workspaces/Projects:/projects:rw"
          ]
        }
      }
    }
  }
}
#

Then have the agent use absolute paths like /projects/<repo>.

Option C (what you were trying to do): mount into workspace (requires dangerous override)

If you must keep tools.fs.workspaceOnly: true and want the project to appear under /workspace/..., you need the explicit break-glass flag:

{
  agents: {
    defaults: {
      sandbox: {
        docker: {
          dangerouslyAllowReservedContainerTargets: true,
          binds: [
            "/home/node/workspaces/Projects:/workspace/Projects:rw"
          ]
        }
#
      }
    }
  }
}

This is intentionally scary-named because it can shadow core mounts. Use it only if you fully trust the runtime.

Docs:

If you paste your agents.defaults.sandbox + tools.fs config block (and whether you changed sandbox.docker.workdir), I can tell you which of B vs C is the cleanest fit for your setup.

wooden elm
#

"tools": {
"fs":{"workspaceOnly":false},
"sessions": {
"visibility": "all"
},
"agentToAgent": {
"enabled": true
},
"sessions_spawn": {
"attachments": {
"enabled": true
}
},
"deny": []
},

"agents": {
"defaults": {
"sandbox": {
"mode": "non-main",
"workspaceAccess": "rw",
"scope": "session",
"workspaceRoot": "/home/node/.openclaw/sandboxes",
"docker": {
"image": "openclaw-sandbox-browser:bookworm-slim",
"readOnlyRoot": false,
"network": "bridge",
"user": "1000:1000",
"env": {
"LANG": "C.UTF-8",
"SEARXNG_URL": "http://192.168.50.216:8081",
"OPENCLAW_SANDBOX_DNS": "192.168.50.230",
"GH_TOKEN": "${GH_TOKEN}"
},
"memory": "2g",
"cpus": 2,
"binds": [
"/home/node/.openclaw/workspace/projects:/workspace/projects/:rw"
],
"dangerouslyAllowExternalBindSources": true
},
"browser": {
"enabled": true,
"headless": true,
"autoStartTimeoutMs": 30000,
"image": "openclaw-sandbox-browser:bookworm-slim"
}
}
},

vast geodeBOT
#

Your bind is failing for exactly this reason:

  • With workspaceAccess: "rw", OpenClaw mounts the agent workspace into the tool-sandbox container at /workspace.
  • /workspace (and anything under it) is treated as a reserved container path, so a bind target like /workspace/projects gets blocked unless you flip the dangerous override.

Given your config, you don’t need to mount into /workspace at all (because you already have tools.fs.workspaceOnly: false).

Fix (recommended): mount shared Projects somewhere NOT reserved

Change:

"binds": [
  "/home/node/.openclaw/workspace/projects:/workspace/projects/:rw"
]

to something like:

#
"binds": [
  "/home/node/.openclaw/workspace/projects:/projects:rw"
]

Then just use /projects/... paths in the sandbox.

(Also: I’d drop the trailing slash in the container path; it avoids edge-case path normalization issues.)

If you really want it under /workspace/projects

You must opt into the break-glass flag:

"docker": {
  "dangerouslyAllowReservedContainerTargets": true,
#
  "binds": [
    "/home/node/.openclaw/workspace/projects:/workspace/projects:rw"
  ]
}

Docs reference for the dangerous key list:
https://docs.openclaw.ai/gateway/security

One more thing (not your main error, but worth fixing)

You’ve set agents.defaults.sandbox.docker.image to openclaw-sandbox-browser:bookworm-slim. That’s the browser image; for tool execution you usually want openclaw-sandbox:bookworm-slim (or openclaw-sandbox-common:...) and keep the browser image under sandbox.browser.image.

If you apply the /projects mount and it still can’t see files, paste the exact error line from the gateway logs — the next most common issue is “bind source path is inside the gateway container, but Docker is running on the host”, so the daemon can’t see /home/node/... the way you think it can.

wooden elm
#

i have tried the "somewhere not reserved" solution however my agents routinly mess up the location because the agent always searches inside the workspace first then says it cant find the file. i have tired all of the prompting....i once went into the subagent session asked for the /projects folder contents. it said it doesnt exist then i commanded it to ls / then ls /projects andthen it finlly beleived me the projects where there. super inconsistant results

vast geodeBOT
#

What you’re seeing is usually not the mount randomly disappearing — it’s the model “assuming” the filesystem layout and then only updating its belief after you force a real ls.

The most reliable way to stop this is: make the shared project show up as a normal relative folder inside the workspace, so the agent’s “search workspace first” behavior works for you, not against you.

Make projects/ appear inside every agent workspace (via symlink), but mount it at a non-reserved path

1) Host layout (recommended)

Put the shared folder as a sibling of agent workspaces:

/home/node/workspaces/
  frontend/
    (agent md files)
    projects -> ../projects     (symlink)
  backend/
    projects -> ../projects     (symlink)
#
  devops/
    projects -> ../projects     (symlink)
  projects/                     (real shared folder)

Create the symlink in each workspace (example):

cd /home/node/workspaces/frontend
ln -s ../projects projects

2) Sandbox bind (non-reserved target)

Bind the shared folder into the container at /projects (NOT /workspace/...):

#
agents: {
  defaults: {
    sandbox: {
      workspaceAccess: "rw",
      docker: {
        binds: [
          "/home/node/workspaces/projects:/projects:rw"
        ]
      }
    }
  }
}

Now, inside the sandbox:

  • The agent’s workspace is /workspace
#
  • /workspace/projects exists (it’s the symlink)
  • That symlink resolves to /projects (your bind mount)

So the agent can keep using projects/<repo> relative paths and it won’t “miss” the folder by default.

3) Important: keep this setting

This symlink trick breaks if you ever turn this on:

tools: { fs: { workspaceOnly: true } }

Because then OpenClaw will realpath-check and treat symlink escapes as “outside workspace”. You currently have workspaceOnly: false, which is correct for this approach.

Also: your sandbox image is suspicious

You’re using:

#
sandbox.docker.image: "openclaw-sandbox-browser:bookworm-slim"

That’s the browser image. For tool sandboxes, use openclaw-sandbox or openclaw-sandbox-common, and keep the browser image under sandbox.browser.image. Mixing them can lead to weirdness.

Quick sanity check when it “doesn’t exist”

When it claims /projects doesn’t exist, ask it to run (in that same session):

  • ls -la /
  • ls -la /projects
  • ls -la projects (relative)

If ls -la /projects fails at the tool level, then it’s truly not mounted (and we debug docker/gateway-in-docker paths). If it succeeds, it’s just model belief drift, and the symlink layout above usually eliminates it.

If you paste one failing ls -la /projects tool output (error text) + tell me whether your gateway is running inside Docker or on the host, I can tell you if you’re hitting the “Docker daemon can’t see container paths” problem.

wooden elm
#

my gateway is in docker as well but on host network. iam planning on using the break glasss approach because i dont have any concerns with bind mounting the shared project folder to the sandboxed session its files only for the agents backued up by git

vast geodeBOT
#

If your gateway is already running inside Docker, the “break-glass mount into /workspace/...” approach is totally workable — and it also fixes the “agent keeps looking in workspace first” problem, because the shared repo will literally be inside the workspace path it expects.

There are just 2 things to get right in a Docker-gateway setup:

1) Enable the reserved-target override + bind into /workspace/projects

In config:

agents: {
  defaults: {
    sandbox: {
      workspaceAccess: "rw",
      docker: {
        dangerouslyAllowReservedContainerTargets: true,
        binds: [
          "<HOST_PROJECTS_PATH>:/workspace/projects:rw"
#
        ]
      }
    }
  }
}

That’s the specific flag that removes the “Sandbox security: reserved container path …” block.

2) Make sure <HOST_PROJECTS_PATH> is a real host path, not “container-only”

This is the part people trip over when the gateway is in Docker:

  • agents.defaults.sandbox.docker.binds is executed by the host Docker daemon
  • so the bind source must exist on the host filesystem
  • and (practically) it should also exist inside the gateway container, because OpenClaw may validate it before starting the sandbox
#

Best pattern on Linux: mount the host projects directory into the gateway container at the same absolute path, then reuse that same path in binds.

Example:

  1. Pick a host path, e.g. /srv/openclaw/projects
  2. Add an extra mount to the gateway container (docker-compose / OPENCLAW_EXTRA_MOUNTS):
    • /srv/openclaw/projects:/srv/openclaw/projects:rw
  3. Then set your sandbox bind source to /srv/openclaw/projects

So your final bind becomes:

binds: [
  "/srv/openclaw/projects:/workspace/projects:rw"
]
#

Docs for adding extra mounts in the Docker gateway flow:
https://docs.openclaw.ai/install/docker#extra-mounts-optional

One small config cleanup

You probably don’t want sandbox.docker.image: "openclaw-sandbox-browser:..." for the tool sandbox. Use openclaw-sandbox / openclaw-sandbox-common there, and keep the browser image under sandbox.browser.image.


If you tell me what you’re using as the host path for your Projects folder (and what it’s mounted to inside the gateway container), I can suggest the exact bind line(s) so the host daemon + gateway container + sandbox containers all agree.

wooden elm
#

i changed the images to your suggestion and added the bind mount and dangerouslyAllowReservedContainerTargets: true,. now the folder is bind mounted inside the sandbox agent but its just the root and no files

#

you know what i told my agent to look at /projects and not /workspace/projects it can see all the folder structure onder the later

vast geodeBOT
#

That “mount exists but it’s empty” symptom almost always means Docker is bind-mounting an empty directory on the host — i.e. the source path you put in binds doesn’t actually contain your repo on the host Docker daemon.

On Linux, when you do a bind mount and the source path doesn’t exist on the host, Docker will quietly create it (empty), and then the container sees… an empty folder. Exactly what you’re describing.

Why this happens in your setup (gateway is also in Docker)

You used a source like:

/home/node/.openclaw/workspace/projects

That path is very likely only “real” inside the gateway container. The host probably does not have /home/node/... (so Docker created /home/node/... on the host, empty).

Fix: use a host path that exists on the Docker host (or make it exist in both places)

Recommended pattern

  1. Pick a host directory for projects, e.g.
  • /srv/openclaw/projects (or /opt/openclaw/projects, etc)
#
  1. Mount it into the gateway container at the same absolute path (via docker-compose / OPENCLAW_EXTRA_MOUNTS):
  • /srv/openclaw/projects:/srv/openclaw/projects:rw
  1. Then in OpenClaw config, use that same path as the sandbox bind source:
agents: {
  defaults: {
    sandbox: {
      docker: {
        dangerouslyAllowReservedContainerTargets: true,
        binds: [
          "/srv/openclaw/projects:/workspace/projects:rw"
        ]
      }
    }
#
  }
}

Now the path exists:

  • on the host (real files)
  • inside the gateway container (same path)
  • and the sandbox container gets the real files

Quick diagnostic (to confirm)

On the Docker host, run:

ls -la /home/node/.openclaw/workspace/projects

If that shows empty (or the dir didn’t exist until now), that’s the problem.

#

If you paste your docker compose volume mounts for the gateway (or the output of docker inspect <gateway-container> | jq '.[0].Mounts'), I can tell you exactly what host path you should point the sandbox bind at.

#

Yep — that’s consistent with your current bind target.

If your config is binding into:

... : /workspace/projects :rw

then /workspace/projects is where the files will be. /projects won’t exist unless you also mount (or symlink) something there.

What to do (best for “agents always look in workspace first”)

Just standardize on a workspace-relative path:

  • use projects/... (relative), or
  • use /workspace/projects/... (absolute)

Because the sandbox tool cwd is /workspace, projects is the most natural and tends to be the least confusing for models.

#

If you really want /projects

Change the bind target to /projects instead:

binds: [
  "<HOST_PROJECTS_PATH>:/projects:rw"
]

…but then you lose the “it’s inside the workspace” advantage unless you also create a symlink projects -> /projects.

If switching to projects/... resolves the confusion, you’re basically done; at that point it’s worth updating each agent’s AGENTS.md with a single line like “Project root: projects/” so it sticks.