Skip to main content
You’re capturing context all week: deploy sessions, incident notes, customer chats. Some of it belongs to a working set you care about right now: the launch. Tags let you mark that set as you go, then search inside it and nothing else.
The SDK manages agent resources only, so its tags live at the project level (plus your account-wide agent registry at /agents/tags in the app). Your personal and team vocabularies are managed in the app (Vault → Sources → Manage tags, and a team vault’s Settings). MCP is read-side only where tags are concerned. There is no tag tool: an agent connected over MCP can filter on a tag you already applied, through pull_context’s filters.tags, and that is the whole of it. Creating and applying tags happens in the app or over the SDK. The filter is a hard scope: only sources you tagged (and the knowledge distilled from them) come back. An untagged note never sneaks in, which is the point of curating. Two more rules do the rest:
  • The vocabulary is deliberate. apply never invents tags: unknown names come back in unknown and the call still succeeds; the backend invalidates anything that doesn’t exist, on every surface. (Your personal vocabulary is seeded on first use with work, health, personal, finance, tech, pii, confidential. Project vocabularies start empty on purpose.)
  • Visibility follows the scope. Personal tags are yours alone; team and project vocabularies are shared with every member. Agent-global tags belong to the account: an agent vault resolves the vault OWNER’s global registry, so collaborators on your projects can see and apply your global tags there. Anyone with vault access can apply a shared tag; detaching a team or project tag from a source needs writer access.

Tags or metadata keys?

One question decides it: should a source that says nothing about this still show up in a filtered search? If yes (keep the general refund-policy note when searching one customer’s context) you want a metadata key. If no (only my curated set) you want a tag. Anti-example both ways: a tag per customer (customer-sara) is a metadata key wearing a tag costume; a declared key for vibes (topic: infra) is a tag wearing a metadata costume. Values → metadata. Groups → tags.

Scoped pull_context

Agents connected over MCP get the same filter on pull_context:
Three things to know on either surface:
  • Unknown tag names fail loud. The SDK returns a 400 listing your vocabulary; MCP returns items: [] with the reason in coverage_note, so read coverage_note before concluding “no memory”.
  • An empty set is an explicit answer. If nothing carries the tag, you get an empty result immediately, not a low-relevance grab bag.
  • Combines with metadata: your curated set, minus anyone else’s data (see the examples below).

Filtering examples

Only the launch set:
Anything tagged either launch or incident (a list means any-of):
The launch set, restricted to one customer (tags + metadata together):

Best practices

  • Name the group, not the value. launch, pii, needs-review, not ticket-8841. Unbounded values are what metadata keys are for.
  • Keep the vocabulary small. Caps are 200 per user and 20 per source; a set you can hold in your head (10–30) is one you’ll actually apply.
  • Create before apply. Unknown names are echoed, never auto-created. That’s typo protection, so don’t fight it by pre-creating variants.
  • Delete is an archive. Sources stay tagged, the tag leaves the pickers, and restore brings it back, so organization is never lost.
  • Don’t push metadata={"tags": [...]}. That key is reserved for a future push-time shape; today it does nothing silently. Tag via tags.apply after the push.

API

  • client.tags.list(project_id): the project’s vocabulary, live counts.
  • client.tags.create(project_id, name) / rename(project_id, tag_id, name) / delete(project_id, tag_id) (archives) / restore(project_id, tag_id). All four need an agent key and project admin; reading the vocabulary needs only membership.
  • client.tags.apply(vault_id, source_id, add=[...], remove=[...]) resolves against the vault’s context: its project’s tags, then your agent-global registry.
  • client.vaults.pull(vault_id, query, filters={"tags": [...]}).