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

# Two agents, one space

> Shared knowledge with per-agent working sets, so a handoff carries everything the next agent needs and none of the noise it doesn't.

[← All use cases](/use-cases/overview)

<div className="uc-examples"><a href="https://github.com/anonalabs/Anona-Memory-SDK/blob/main/examples/multi_agent_shared_space.py">multi\_agent\_shared\_space.py</a></div>

## The scenario

A researcher agent gathers facts. A writer agent turns them into copy. They are
separate agents with separate prompts, and each accumulates notes the other
should never see — the writer's drafting angles are not findings, and the
researcher's raw scraps are not a brief.

The naive options are both bad. One space each means the writer cannot see what
the researcher learned, so you end up passing findings through the orchestrator
by hand. One space with no separation means every read returns both agents'
working notes mixed together, and quality degrades as the pile grows.

What you want is one space, two working sets, and a handoff that costs nothing.

## Step 1 — Each agent writes under its own scope

`agent_id` works like `user_id`, but it identifies the *writer* rather than the
end user.

```python theme={null}
client.record(
    space_id=space,
    content="Competitor X launched usage-based pricing at $0.80 per thousand calls.",
    agent_id="researcher",
)
client.record(
    space_id=space,
    content="Draft angle: lead with predictable pricing, avoid feature tables.",
    agent_id="writer",
)
```

## Step 2 — A scoped read is that agent's working set

```python theme={null}
client.retrieve(space_id=space, query="drafting notes", agent_id="writer")
```

Returns the writer's notes and nothing else. The researcher's findings are in
the same space and do not appear, because the read asked for one scope.

## Step 3 — An unscoped read is the handoff

```python theme={null}
client.retrieve(space_id=space, query="What do we know about competitor X?")
```

Returns everything the space knows, whoever wrote it. **This is the whole
mechanism** — the writer's prompt pulls the researcher's findings without
knowing who produced them, without an orchestrator passing state, and without a
second API call to stitch two spaces together.

Add a scope to narrow. Leave it off to hand off.

## Evals

A handoff either carries the knowledge or it does not, and that is testable:

1. Have agent A write three facts under `agent_id="a"`, and agent B write two
   notes under `agent_id="b"`.
2. Read with `agent_id="b"` — assert none of A's three come back.
3. Read with no scope, asking A's question — assert A's facts come back.
4. Grow B's notes to fifty and repeat step 3. If A's facts stop surfacing, the
   unscoped read is competing against B's volume and the handoff needs a
   narrower query, not a bigger limit.

Step 4 is the one worth automating. A handoff that works on day one and degrades
at scale is the failure mode this design is exposed to.

## Guardrails

<Warning>
  **Scoping is not a security boundary between your own agents.** Any caller
  holding the API key can read any scope in the space — the separation is about
  relevance, not access control. For a boundary that holds against a different
  *organization*, share the space and use
  [per-space roles](/api-reference/spaces) instead.
</Warning>

* **A scoped query is strict.** Memories written before you adopted `agent_id`
  carry no scope, so a scoped read will never match them. Adopt scoping at the
  start of a space's life, or backfill.
* **Unscoped writes stay unscoped.** Calls without a scope key produce exactly
  the request they always did, so adding `agent_id` to one agent does not
  change what the other already stored.
* **Pick the right key for the job.** `agent_id` identifies the writer,
  `user_id` the end user this is about, and `session_id` one run or
  conversation. They compose — a support agent serving many customers uses both
  `agent_id` and `user_id`. See
  [Scoping Memory by User, Agent, or Session](/guides/scoping-multi-tenant).
* **Observations consolidate per user, not per agent.** Synthesis across an
  agent's notes follows the user scope first. If you need per-agent synthesis,
  that is a [memory model](/api-reference/models), not a scope.

## The script

Complete and runnable:
[`multi_agent_shared_space.py`](https://github.com/anonalabs/Anona-Memory-SDK/blob/main/examples/multi_agent_shared_space.py).

See also [One space, many end users](https://github.com/anonalabs/Anona-Memory-SDK/blob/main/examples/support_bot_scoping.py)
for the same mechanism applied to end users rather than agents.
