Give every 1:1 its own direct conversation instead of piling into #general

Agents could only post to named public channels - the messaging tool even
excluded direct spaces - so assignments, reports, and questions all crowded
into general. Now ChatService.ensureDirectSpace finds or creates the private
two-member conversation for any agent/employee pair; send_message takes
to="Name" for 1:1 traffic (exactly one of to/channel), read_messages reads a
conversation by teammate name, and task assignments land in the manager's DM
with the assignee. In a direct conversation the counterpart agent wakes on
every message without needing an @mention - same social contract as any
messenger - still bounded by the autonomous-turn budget, and wake task
briefings tell agents to reply with to= in kind. Covered by six new
direct-message contract tests; the assignment-thread test now encodes the
DM routing contract.
This commit is contained in:
ZacharyZhang-NY committed 2026-07-06 22:49:31 -04:00
1 parent f13ef48a3e
commit cab7b01831
6 files changed
+375 -51

No files matched your search

@@ -186,12 +186,17 @@ describe("agent run loop (real tool dispatch)", () => {
const alex = connection.db.prepare("select id from agents where org_id = ? and name = 'Alex Rivera'").get(orgId) as { id: string };
const assignment = connection.db.prepare(`
select m.body_md, m.thread_id, s.name as space_name
select m.body_md, m.thread_id, s.id as space_id, s.space_type
from chat_messages m
join chat_spaces s on s.id = m.space_id
where m.org_id = ?
`).get(orgId) as { body_md: string; thread_id: string; space_name: string } | undefined;
expect(assignment).toMatchObject({ space_name: "engineering" });
`).get(orgId) as { body_md: string; thread_id: string; space_id: string; space_type: string } | undefined;
// Assignments are 1:1 hand-offs, so they live in the manager's direct
// conversation with the assignee instead of a shared channel.
expect(assignment).toMatchObject({ space_type: "direct" });
const dmMembers = connection.db.prepare("select principal_id from chat_memberships where space_id = ?")
.all(assignment?.space_id ?? "") as Array<{ principal_id: string }>;
expect(dmMembers.map((m) => m.principal_id).sort()).toEqual([ceoId, alex.id].sort());
expect(assignment?.body_md).toContain(`@${canonicalMentionHandle("Alex Rivera")}`);
expect(assignment?.body_md).toContain("Build the booking API");