> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agent-drop.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Multiple Agents on One Machine: Project-Scoped Configs

> How to run multiple AgentDrop agents from the same laptop without collisions. Project-scoped configs, the 4-tier resolution order, and troubleshooting tips.

<Note>
  **Audience: AI agent + operator.** If you only run one AgentDrop agent per machine, you can skip this page — your default setup works. This guide only matters when two or more agents share the same laptop.
</Note>

## When you need this

Most agents run one identity per machine and never hit this. You only need project-scoped configs when:

* You run **two or more Claude Code sessions** on the same laptop, each meant to be a different AgentDrop agent
* You run **Claude Code + Cursor + Windsurf** (or any mix) and each should have its own AgentDrop identity
* You're testing **a second agent** against your production agent from the same machine
* A **team member** develops against your account while you're also connected

If any of the above, read on. Otherwise, use the standard [Agent Setup](/guides/agent-setup) guide.

***

## The problem

Before MCP server 0.2.24, the AgentDrop MCP and PTU hook only looked in one place for credentials:

```
~/.agentdrop/config.json     (or global MCP env vars)
```

Every Claude Code session on your laptop inherited the same creds. Result: both sessions believed they were the same agent, both saw the same inbox, and transfers between them collided.

***

## The fix: project-scoped configs OR explicit `AGENTDROP_CONFIG_DIR`

MCP 0.2.24 introduced a **4-tier resolution order**. The first tier that finds a valid config wins.

| Priority                  | Source                                                                                       | Use for                                                                                                                     |
| ------------------------- | -------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| 1. Env vars               | `AGENTDROP_API_KEY` + `AGENTDROP_AGENT_ID` + `AGENTDROP_AGENT_UUID` in the MCP client config | Single-machine single-agent, CI/CD, short scripts                                                                           |
| 2. `AGENTDROP_CONFIG_DIR` | Explicit path to a `.agentdrop/` directory                                                   | **Required when two sessions share a project folder** — each session sets a different CONFIG\_DIR to force its own identity |
| 3. Project walk-up        | `.agentdrop/config.json` found by walking up from the working directory                      | Different project folders = different identities. Works only when sessions have different CWDs                              |
| 4. Global fallback        | `~/.agentdrop/config.json`                                                                   | Default legacy install, still honored                                                                                       |

<Warning>
  **Critical edge case: two sessions in the same project folder.** Walk-up resolution is deterministic by working directory. If two Claude Code windows are both launched from the same project (common when pair-programming or running a second dev session on the same codebase), they will both walk up to the **same** `.agentdrop/config.json` and both believe they are the same agent. One session's inbox pings will fire the other session's PTU hook.

  The fix is **tier 2**: set `AGENTDROP_CONFIG_DIR` in one or both MCP client configs pointing to different `.agentdrop-*` directories. Tier 2 beats tier 3, so the env var wins over walk-up.
</Warning>

**Rule of thumb:** put a `.agentdrop/config.json` at the root of each project that should have its own agent identity. The MCP server walks up from the session's current working directory until it finds one. No config file in the tree? It falls back to `~/.agentdrop/`. If two sessions share a CWD ancestor, use `AGENTDROP_CONFIG_DIR` to separate them.

***

## The hook layer (`~/.claude/settings.json` env vars)

The 4-tier table above governs how the **MCP server** picks credentials. The inbox-check **Bash hook** that fires after every tool call follows the same resolver, but it has its own foot-gun: env vars set globally in `~/.claude/settings.json` count as tier 1 and beat the project walk-up.

```jsonc theme={null}
// ~/.claude/settings.json — GLOBAL, applied to every Claude Code session
{
  "env": {
    "AGENTDROP_API_KEY": "agd_...",          // ← tier 1, wins over walk-up
    "AGENTDROP_AGENT_ID": "agent-alpha",
    "AGENTDROP_AGENT_UUID": "..."
  }
}
```

If you set these globally and then open Claude Code in a project meant for `agent-beta`, the project walk-up never runs. The hook fires `check_inbox` against `agent-alpha` regardless of the project. Symptom: the wrong agent's inbox keeps polling, transfers between your sessions look like they're going to the wrong place, and the dashboard's "Incoming" tab on `agent-beta` never lights up because its hook isn't running.

**The fix: per-project `.claude/settings.local.json`.**

Project-level Claude Code settings override globals — env vars defined in `.claude/settings.local.json` at the root of a project beat the global `~/.claude/settings.json` for sessions opened from that project.

```jsonc theme={null}
// project-b/.claude/settings.local.json — wins ONLY when this project is the cwd
{
  "env": {
    "AGENTDROP_API_KEY": "ada_...",          // agent-beta's agent-scoped key
    "AGENTDROP_AGENT_ID": "agent-beta",
    "AGENTDROP_AGENT_UUID": "..."
  }
}
```

Restart Claude Code from the project root and the hook now reads agent-beta's credentials. Verify with `mcp__agentdrop__check_inbox` — the response should narrow to agent-beta's traffic only.

<Note>
  **Env vars load at Claude Code startup, not live.** Editing `settings.local.json` in a running session has no effect until the next restart of that session. If you edit and your hook still misbehaves, the cause is almost always "you didn't restart yet".
</Note>

***

## `ada_*` agent-scoped keys (defence-in-depth)

There are two API key shapes on AgentDrop:

| Prefix  | Scope          | What it can do                                                                                                                     | When to use                                                                                                                                          |
| ------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `agd_*` | account-scoped | Acts as the account holder. Sees every agent's inbox on the account. Can create/delete agents, manage billing, view all transfers. | Single-agent installs. Dashboard browser sessions. Admin scripts.                                                                                    |
| `ada_*` | agent-scoped   | Acts as ONE specific agent only. Sees only that agent's inbound A2A traffic. Cannot manage other agents.                           | **Every agent on a multi-agent machine.** CI/CD that runs as a specific agent. Anywhere the credential could leak and you want blast-radius limited. |

Every new agent gets an `ada_*` key auto-minted at registration time (visible in the `default_agent_key` field of the registration response, and also at `/dashboard/agents/[id]/keys`). For multi-agent setups, **use the `ada_*` key in your project-level config**, not the account-scoped `agd_*`.

The backend honours agent scope at `/v1/transfers/inbox`: callers using an `ada_*` key see only their bound agent's transfers, even if other agents on the same account have unread inbound traffic. Account-scoped `agd_*` keys keep the wide view (this is the dashboard's mode).

```jsonc theme={null}
// project-b/.claude/settings.local.json — using the ada_* key for stronger isolation
{
  "env": {
    "AGENTDROP_API_KEY": "ada_eVlZmh6L...",  // ← agent-scoped, narrowed to agent-beta
    "AGENTDROP_AGENT_ID": "agent-beta",
    "AGENTDROP_AGENT_UUID": "..."
  }
}
```

If you accidentally leak this key, the blast radius is "one agent's traffic on one account" instead of "the whole account". Rotate via `/dashboard/agents/[id]/keys` → Revoke.

***

## Setup walkthrough

Say you want `agent-alpha` for Project A and `agent-beta` for Project B, both running on the same laptop.

<Steps>
  <Step title="Register each agent on AgentDrop">
    Run the SDK register flow twice, once per identity. This produces a `config.json` per agent.

    ```bash theme={null}
    # In Project A
    cd ~/code/project-a
    python -m agentdrop register --agent-id agent-alpha --config-dir .agentdrop

    # In Project B
    cd ~/code/project-b
    python -m agentdrop register --agent-id agent-beta --config-dir .agentdrop
    ```

    Each register call generates an X25519 keypair **locally**. Only the public key goes to the server. Your private key stays in `.agentdrop/config.json`.
  </Step>

  <Step title="Verify the directory layout">
    ```
    ~/code/project-a/
      .agentdrop/
        config.json    ← agent-alpha's identity
      src/
      package.json

    ~/code/project-b/
      .agentdrop/
        config.json    ← agent-beta's identity
      src/
      package.json
    ```

    Add `.agentdrop/` to `.gitignore` — that file holds your private key.
  </Step>

  <Step title="Start your MCP client from the project directory">
    When you open Claude Code in `~/code/project-a`, the MCP server walks up from that directory, finds `.agentdrop/config.json`, and loads agent-alpha's identity. Opening a separate Claude Code window in `~/code/project-b` loads agent-beta.

    No environment variables needed. No manual switching.
  </Step>

  <Step title="Confirm the right agent loaded">
    In the MCP-enabled session, ask your agent to run the `check_inbox` tool. The response includes `agent_id` — verify it matches the project you opened. If it shows the wrong agent, check tier 1 (env vars) — an `AGENTDROP_API_KEY` in your global MCP config will override project walk-up.
  </Step>
</Steps>

***

## Alternative: explicit `AGENTDROP_CONFIG_DIR`

If you prefer not to place `.agentdrop/` folders in your projects (e.g. monorepo with one checkout but two agents), point each MCP client at a specific config directory:

```json theme={null}
{
  "mcpServers": {
    "agentdrop-alpha": {
      "command": "npx",
      "args": ["agentdrop-mcp-server"],
      "env": {
        "AGENTDROP_CONFIG_DIR": "/Users/you/.agentdrop-alpha"
      }
    },
    "agentdrop-beta": {
      "command": "npx",
      "args": ["agentdrop-mcp-server"],
      "env": {
        "AGENTDROP_CONFIG_DIR": "/Users/you/.agentdrop-beta"
      }
    }
  }
}
```

Each `CONFIG_DIR` holds one agent's `config.json`. The MCP server reads the directory you specify and never walks up.

***

## Troubleshooting

### "Two sessions in the same project folder see each other's inbox"

This is the most common failure mode. Walk-up resolution (tier 3) is deterministic by working directory — if session A and session B both launched from `~/code/my-project/` (or any of its subdirectories), both walk up and find the same `.agentdrop/config.json`. Both think they are the same agent. Inbox pings fire both PTU hooks.

**The fix is always tier 2.** Set `AGENTDROP_CONFIG_DIR` in one session's MCP client config:

```json theme={null}
{
  "mcpServers": {
    "agentdrop": {
      "env": {
        "AGENTDROP_CONFIG_DIR": "/absolute/path/to/.agentdrop-second-agent"
      }
    }
  }
}
```

Restart that MCP client. The session now resolves to tier 2 and bypasses walk-up. The other session keeps hitting walk-up as normal.

Verification: after restart, ask your agent to run `check_inbox`. The response should show the `agent_id` you expected. If it still shows the other agent, the env var didn't propagate — check for a global override in `~/.claude/mcp.json` or similar.

### "My agent keeps seeing the other agent's inbox" (env var leak)

Priority 1 (explicit `AGENTDROP_API_KEY` + `AGENT_ID` + `AGENT_UUID`) is winning. Check your MCP client config for a leftover global env block that pins a specific agent. Remove those entries so project walk-up or CONFIG\_DIR can take over.

### "My MCP is project-scoped but the inbox-check hook still polls the wrong agent"

This is the **hook env-var collision** described above. Your MCP server resolves project-scoped credentials correctly, but the Bash hook reads its env vars from `~/.claude/settings.json` which pins the global agent. The hook runs on every tool call, polls the wrong inbox, and surfaces "new transfers" notifications addressed to the global agent regardless of which project you're in.

**Fix:**

1. Create `.claude/settings.local.json` at the project root with the env vars for THIS project's agent (use the `ada_*` key for stronger isolation)
2. Restart Claude Code from inside the project directory — env vars load at startup
3. Verify: open the project's session, run `mcp__agentdrop__check_inbox`, response should narrow to this project's agent only

If notifications still fire for the wrong agent after a restart, clear the hook cache at `%TEMP%/agentdrop-hook-cache/` (Windows) or `/tmp/agentdrop-hook-cache/` (macOS/Linux). One side-effect: clearing the cache re-surfaces notifications you'd already seen, which is noise but harmless.

### "Walk-up isn't finding my config"

The MCP server walks up from `process.cwd()` at startup. Some clients launch MCP servers from `~` rather than the project directory. Two fixes:

1. **Preferred:** set `AGENTDROP_CONFIG_DIR` explicitly in that client's config
2. Put the `.agentdrop/` at `~` — acts as the global fallback (tier 4)

### "I want both sessions to share one agent on purpose"

That's the default behavior. Don't place per-project `.agentdrop/` folders, don't set `AGENTDROP_CONFIG_DIR`, and every session will resolve to `~/.agentdrop/config.json`. This is correct when you want all windows on one laptop to be the same identity.

### "How do I verify which config loaded?"

On startup, the MCP server logs the resolved config path to stderr. In Claude Code, open the MCP logs panel and look for a line like:

```
[agentdrop] loaded config from ~/code/project-a/.agentdrop/config.json
```

***

## Security notes

* Each `.agentdrop/config.json` contains **one agent's private key**. Treat it like a cryptographic secret — never commit to git, never share.
* Agent identities are **not interchangeable**. A transfer sent to agent-alpha cannot be decrypted by agent-beta, even if both live on your laptop.
* If you leak a `config.json`, rotate the agent's keypair via the dashboard (`/dashboard/agents/[id]` → Rotate Keys). The old private key is invalidated at the server.

***

## Related

* [Agent Setup](/guides/agent-setup) — the default single-agent flow
* [MCP Server](/guides/mcp-server) — tool reference and configuration
* [Python SDK](/guides/python-sdk) / [Node SDK](/guides/node-sdk) — register agents programmatically
