user_id that ingested it. Groups let you share memory across users: tag a memory to a group at ingest, and anyone who searches that group can see it.
The motivating case is collaborative agents — e.g. a travel-planning assistant where each trip is a group. Every traveler’s AI tags trip-relevant facts to the trip’s group, so the whole party shares one evolving picture (hotels, restaurants, dates) while each person’s unrelated personal memories stay private.
The model
- A group is a registry entry with a
nameand aprompt. Thepromptdescribes what belongs in the group — it’s what the ingest classifier reads to decide which extracted memories to tag. - Group ids are server-generated, unguessable handles (
grp_…). Knowing the id is the access boundary — your client decides which users belong to which groups and which ids to send; the memory service doesn’t track membership. - Tagging is additive: tagging a memory to a group never removes it from the author’s own scope.
1. Register a group
prompt the way you’d brief the classifier: concrete about what to include. A sharp prompt (“facts about the Tokyo trip”) tags precisely; a vague one over- or under-tags.
2. Tag memories at ingest
Pass the group ids ingroup_ids. At extraction time the classifier reads each group’s prompt and tags the extracted memories that belong to it.
- Each extracted memory is tagged with the subset of
group_idsit belongs to — several, one, or none. (“Stays near Shibuya” → tagged to the Tokyo trip; “I’m vegetarian” → likely left untagged, as a general preference.) - Unknown or archived ids are soft-skipped (never fail the ingest) and returned in
result.ignored_group_ids. - Up to 20 group ids per ingest; more returns
422.
3. Read shared memories back
The whole group, across every member — omituser_id, pass group_ids:
recall:
recall sections the prompt by Personal + the group’s name and attributes each shared line to its author (you: for the caller, <user_id>: for fellow members). See Searching memories for the full picture, including how AND-scoping makes { user_id, group_ids } on a plain search an intersection rather than a union.
Group membership matching is any-of: pass
group_ids: [tripA, tripB] to search across both trips at once (a user can belong to many groups).Managing groups
status becomes "archived"): the group stays readable, but it’s dropped from future ingest tagging — a stale id passed on ingest just lands in ignored_group_ids. Re-activate by update(id, { status: 'active' }).
Best practices
Model a group around a real shared boundary. A group should map to something multiple users genuinely share — a trip, a project, a workspace channel — not a single user (that’s whatuser_id is for) and not a throwaway topic. If only one person will ever read it, it doesn’t need to be a group.
Write the prompt like a brief to the classifier. It’s the only signal used to decide what gets tagged. Name the subject so unrelated facts don’t leak in:
| Prompt | |
|---|---|
| ✅ Sharp | ”Facts about the Tokyo trip in May 2026: flights, hotels, restaurants, reservations, and dietary needs for this trip.” |
| ❌ Vague | ”Travel stuff.” — over- or under-tags |
group_ids relevant to this conversation, not every group in the org. A tighter list means sharper tagging and less cross-trip noise. (Max 20 per ingest.)
Keep personal personal. Untagged memories stay private to the user — only tagged ones cross to the group. Scope the group prompt to genuinely shared concerns so a user’s general preferences don’t get pulled into a group they don’t belong in.
Pick the right read for the job:
- An agent serving one user inside a group →
recall({ pools: [{ user_id }, { group_ids }] })— their own context plus the group’s, deduped and attributed. - A whole-group overview (“what does the trip know?”) →
search({ group_ids }), omituser_id. - Don’t expect
search({ user_id, group_ids })to union — it’s an intersection (see Searching memories).
result.ignored_group_ids to catch unknown or archived ids.
Group ids are the access boundary. They’re unguessable (grp_…) and the service doesn’t track membership — your app decides who can read a group. Don’t expose a group id to anyone who shouldn’t see the group, and don’t tag anything you wouldn’t want every member to read.
Archive groups when they’re done. A finished trip shouldn’t keep collecting tags; archive it to stop new tagging while keeping its history readable.
See also
- Ingesting memories — the
group_idstagging path - Searching memories — scoping,
recall, search modes - TypeScript SDK —
client.groupsmethod reference