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

# ADR-33: ADR-33

> # Title Agent name uniqueness is `(user_id, project_id, display_name)` — per-User-per-Project  # Decision The `agents` table enforces `UNIQUE(user_id, project_i

<Info>**Status:** `accepted` · **ADR-33** · Filed 2026-04-30</Info>

# Title

Agent name uniqueness is `(user_id, project_id, display_name)` — per-User-per-Project

# Decision

The `agents` table enforces `UNIQUE(user_id, project_id, display_name)`. Display name "Donna" can recur:

* Across different projects in the same Org (Frank's "Donna" in Project X is independent of Frank's "Donna" in Project Y).
* Across different users within the same project (Frank's "Donna" and Joe's "Donna" can coexist in Project X).
  The agent\_id is a stable UUID PK; display name is the user-facing label.

Resolution for `to_agent="display_name"` searches within the sender's project scope, prefers the sender's own user\_id when multiple matches exist, and errors with disambiguation hint when ambiguous. Cross-user disambig syntax `to_agent="display_name@user_login"` is reserved.

# Rationale

Three orthogonal concerns drive this:

1. **Project scope = routing reach.** SPEC-056 locks the rule that an agent can only address other agents in the same project. Persona name uniqueness must be at the same scope or tighter — naming uniqueness scoped wider than routing reach creates ambiguity (which "Donna" did Frank's send target?). Per-project naming + project-scoped reach is concentric and clean.
2. **User axis = ownership.** The agent's owner (the human persona-assigner) is a real distinguisher. Two collaborators on the same project will both want their own persona names without one of them being forced into "Donna2." Pulling user\_id into the uniqueness key gives each owner their own naming namespace within the project.
3. **Display name is mutable.** Renames are name-only; agent\_id is the durable identity. The unique constraint is a soft constraint enforcing UX, not a primary key. Composite key forms (e.g., `(project_id, display_name)` at the PK level) are rejected in favor of UUID PK + UNIQUE constraint.

This decision contradicts an earlier mid-noodling lean toward per-Org uniqueness; the per-Project rule was settled after Frank reframed routing as project-scoped and called out the multi-user same-project scenario.

# Alternatives Considered

1. **Per-Tenant unique** — "Donna" is one person across all Orgs in Acme. Cleanest for cross-Org collab but forces every department to coordinate naming. Rejected.
2. **Per-Org unique** — Donna is shared across all of Engineering's projects. Initially appealing but doesn't compose with multi-user-per-project (two Engineering humans both want "Donna"). Rejected.
3. **Per-Project unique without user\_id axis** (`UNIQUE(project_id, display_name)`) — current behavior; doesn't allow two collaborators in the same project to both name a persona "Donna." Rejected as the multi-user scenario is a near-term reality.

# Status

accepted

# References

* SPEC-056 §Identity model + §Routing rules
* Memory: `project_signal_isolation_multitenant`
