Chat and contacts
- One conversation experience: 1:1 with a colleague, 1:1 with an agent, and workspace group chat share the conversation list, bubble timeline, attachments, and unread.
Source docs/en/site/mech-im.md
Status: Product decision confirmed (2026-05-23), pending implementation.
Truth: User-visible capabilities follow docs/产品规格.md §4.6; this page is for design and implementation mapping.
Voice: UI and help use user language; table names and paths appear only here.
1. Goal
- One conversation experience: 1:1 with a colleague, 1:1 with an agent, and workspace group chat share the conversation list, bubble timeline, attachments, and unread.
- An agent is a kind of “conversation member”: can chat 1:1, can join a group; the owner can list the agent on a public marketplace for others to lease.
- People rules by scene: trusted free chat with same-workspace colleagues; non-colleague strangers “one message → short window after a reply → long-term needs to be friends”.
Relation to today’s /api/v1/chat + chat_sessions (user ↔ LLM, help assistant): mid-term converge on a unified conversation model; agent replies still go through Cadau Runtime, but conversation members, groups, and lease auth go through a new domain (illustrative im_* names below).
Human support (docs/core-mechanisms/人工客服.md): after the user hands off to a person, the 1:1 user↔support created when a seat claims the ticket uses im_* contacts; it is a separate track from agent LLM chat and service notices.
2. Confirmed product decisions (summary)
| # | Topic | Decision |
|---|---|---|
| 1 | Architecture | Unified conversations; agents alongside people; leased agents can join groups |
| 1a | Display | Agent identity first; both lessor and lessee may set a display alias |
| 1b | Entitlement | Phase 1 public marketplace (browse, apply / paid lease) |
| 1c | Quota | Billing party follows the lease contract / plan |
| 1d | Join a group | The lessee may add a leased agent to groups they have permission for |
| 2 | Colleague 1:1 | Same-workspace members are trusted; chat freely |
| 3 | Non-colleague 1:1 | 1 message before a reply → short-term after a reply (days/count in implementation) → long-term requires friends |
| 4 | Workspace groups | Default all-member group + custom subgroups; members sync with the workspace (all-member group) |
3. Conversations and members (implementation model)
3.1 Conversation type conversation.type
| Type | Note | |
|---|---|---|
direct | Two people (or “person ↔ agent”) 1:1 | |
workspace_group | Workspace group; subtype: all_member \ | custom |
3.2 Member conversation_member.member_kind
| kind | Identifier | Note |
|---|---|---|
user | user_id | A person |
agent | user_agent_id | User agent; related owner_user_id |
When a group message comes from an agent: sender_kind=agent, and record operated_by_user_id (the person who triggered the lease, if any).
3.3 Versus “runtime Workspace”
- Product workspace
workspace_id: collaboration boundary, all-member group ownership. - Runtime Workspace (
SOUL.mdand similar): still belongs to a singleuser_agent_idinstance; in a leased conversation, Runtime context must bind lessee + workspace (if the group is in a workspace) + lease-contract policy.
4. Agent leasing (public marketplace)
4.1 Entities (illustrative)
agent_listings: listing (description, skill tags, price/plan reference, visibility).agent_leases: lease order; statuspending | active | expired | revoked; includes billing terms (usage charged to lessor / lessee / workspace).agent_display_aliases:(viewer_user_id, user_agent_id) -> display_name; lessor and lessee may each set an alias (display prefers the alias; original name remains viewable).
4.2 Auth
- Sending a message to a leased agent: check
agent_leases.activeandlessee_user_id = current user(or operators allowed by the contract). - Pulling an agent into a group: check group eligibility + lease right (decision A).
4.3 Billing
- On conversation debit, pick lessor quota / lessee quota / workspace quota by
lease.billing_policy(contract). - Admin can audit: conversation id, message id, token usage, lease id.
5. People-message rules
Account-level capabilities: adding friends and 1:1 with a person do not require already joining a workspace; only workspace groups and colleague-trust rules depend on workspace_members.
| Relationship | Rule |
|---|---|
| Mutual friends | Free chat |
| Same-workspace members (at least one shared workspace) | Free chat (trusted) |
| Neither colleague nor friend | First message only 1 → after they reply, a short-term window → after it expires, must be friends to continue |
| Block | One-way refuse send/receive |
Implementation fields (1:1 direct): stranger_phase: none | locked | short_term | friend; short_term_expires_at; the server enforces before POST message.
Agent conversations: stranger count limits do not apply; only ownership or lease is checked.
6. Workspace groups
- All-member group: created automatically with the workspace; members join/leave the group when they join/leave the workspace.
- Subgroups: members or admins create them; invite policy can be phased (phase 1: group admins pull people in).
- A group may have people + authorized/leased agents; after @ an agent or a trigger policy, Runtime generates a reply (async task, written to
im_messages).
7. API draft (prefix /api/v1/im/)
| Method | Path | Note |
|---|---|---|
| GET | /im/conversations | Current user’s conversation list (including unread) |
| POST | /im/conversations/direct | Start 1:1 { peer_user_id } or { user_agent_id } |
| GET | /im/conversations/{id}/messages | History pagination |
| POST | /im/conversations/{id}/messages | Send (idempotent client_message_id) |
| POST | /im/conversations/{id}/read | Read watermark |
| GET/POST | /im/friend-requests … | Friend requests |
| GET | /im/friends | Friend list |
| POST | /im/blocks | Block |
| GET | /im/agent-listings | Public marketplace list |
| POST | /im/agent-leases | Lease / apply |
| PATCH | /im/agent-aliases | Display alias |
| GET | /workspaces/{id}/conversations | Workspace-related groups (including default all-member group id) |
| POST | /workspaces/{id}/groups | Create a subgroup |
Example error codes: stranger_quota_exceeded, lease_required, not_group_member, peer_blocked.
Realtime: phase 1 poll GET /im/sync?since=; phase 2 WebSocket.
8. Client
- Today’s top-bar Messages evolves into a unified conversation entry (the list includes people, agents, groups); talking with an agent no longer uses an IA that is only a
chat_sessionslist (migration may be dual-track). - Area B (if kept): show members of the current conversation (including leased-agent aliases), not only an “agent marketplace” list.
- Workspace collaboration member rows: “Send a message” / “Lease their agent” jump to unified chat or the marketplace.
9. Suggested phases
| Phase | Content |
|---|---|
| P0 | Tables + 1:1 (person↔person rules + person↔own agent) + friends |
| P1 | Default all-member group + subgroups + in-group messages |
| P2 | Marketplace listing + lease + aliases on both sides + billing terms |
| P3 | Leased agents join groups + in-group Runtime replies |
| P4 | Migrate old chat conversations, WS push, mobile |
10. Related documents
- docs/产品规格.md §4.6
- docs/界面与布局.md (after unified chat, the “Messages” area description needs revision)
- docs/产品规格.md §3.6 / §7.4 (agent marketplace and training)