#Convex Agents for multi-tenant applications?

10 messages · Page 1 of 1 (latest)

static root
#

Hi Convex team,

I'm implementing a multi-tenant application with the Convex Agent component where:

  • Each tenant represents an organization with multiple users
  • Users have different roles and permissions within the organization
  • We need agents to access context across users within the same organization

I've explored using tenant-prefixed userIds (like account:${accountId}:user:${userId}) which works well for tenant isolation, but I noticed a limitation: when searchOtherThreads is enabled, it only searches for the exact prefixed userId and not other users in the same organization.

Questions:

  1. What's the recommended approach for sharing context across users within the same organization while maintaining tenant isolation?
  2. Is there a built-in way to implement organization-wide knowledge bases that all users within a tenant can access?
  3. Are there any plans to enhance the Agent component with more flexible context retrieval options, such as custom filters for userId patterns?

I've considered workarounds like:

  • Creating shared organization threads with special userIds (like account:${accountId}:shared:kb)
  • Implementing custom context fetching to query across multiple users
  • Using threadId-based lookups more extensively

Would love to hear the team's recommendations on the best approach that maintains clean tenant isolation without sacrificing cross-user context.

Thanks!

Tagging @thick sigil

#

Convex Agents for multi-tenant applications?

thick sigil
#

I'm on vacation until next friday and will be off-grid starting Wednesday, but my initial thoughts:

  • You could use the accountId instead of the userId everywhere, if you don't need to fetch per-user context across threads. I originally was going to name it something like "domainId" or "ownerId" but went with user to make it clearest for the common case.
  • As your context needs get more specific, I think it makes sense to use the vector store directly. That way you have full control over the filters available.
  • In particular, I think once the unit of "context" wants to be more than a message, owning that data in your own custom format and tables makes sense. If Convex could use a simpler "RAG" component that does embedding + vector search, I'm open to suggestions.
  • If you only want to store the messages and are happy with the Agent interface for querying, you could store messages for both the accountId and the userId using saveMessages / saveStep and fetchContextMessages directly.

The library offering would look something like being able to provide an extra layer explicitly which would result in a third "filterField". Currently I namespace the search to either the thread or user by making synthesized fields: one combining the model, table, and userId, another combining model, table, and threadId, so I can do an exact search efficiently. Making these arrays allows you to effectively get an "AND" operation over the vector search fields. So adding a model_table_accountId would be the extension here.

Some open questions would be:

  • Would (future) usage tracking be calculated per-user, per-account, or are both necessary?
  • Are there any requirements that all threads be created in some account?

Overall I think this is lower on the priority list unless more people have the same requirements. So I'd say sticking to the plan of either using the userId for your accountId, adding per-account context manually (passing in an array of messages with the account context, then the last one with the regular prompt - by default it'll only store the last message and will still add context automatically)

GitHub

Build AI agents on Convex with persistent chat history - get-convex/agent

static root
#

Firstly I apologies the inturruption, hope you don't look at discord messages on your remaining vacation day 😛 Secondly thank you the comprehensive response, I think Convex agents are a bit too young at this stage. Maybe I'll try them in another project. Will probably go with Mastra at this stage. Cheers!

thick sigil
#

Just got back, and that makes sense. I'd be interested if you have a list of features Mastra provides that the Agent component should have. I haven't finished the Mastra component - what did you end up doing for storage/vector implementations there? Using Convex at all, out of curiosity?

potent fog
#

@thick sigil has there been any updates on supporting multi-tenant applications. I look at the agents code on GitHub and it seemed like searchOtherThreads functionality hasn’t changed but I just want to confirm

I am working on an application with the requirements of supporting user chats, team chats, and then overall organization chats (i.e. userId, teamId, orgId).

The agent has to be able to search across user chats, team chats, and organization chats when relevant. And there are times where teams shouldn’t be able to look at other teams threads even if they’re in the same organization.

If this hasn’t been updated what are the potential workarounds I could use to solve this problem on convex

snow igloo
#

I'll +1 this request but right now im just using userId as the company id as a company shares the context of the agent chat between users. I could provide greater feedback once i play with it more in my ultra-tenant site. I think what will happen if there is no other way to get other data in is either passing multiple values into userId or giving it my session context id

thick sigil
# potent fog <@897754604790480906> has there been any updates on supporting multi-tenant app...

So if I understand correctly, there are:

  • User <-> LLM chats
  • User <-> Teammate chats (does this also have an LLM involved?)
  • User <-> Coworker chats (same Org) - again does this have LLMs involved?

If there are not LLMs involved, I would structure those as regular chats and do a regular search on those, e.g. to provide as context to an LLM

If each chat has an LLM, are you searching for chats your teammate had with LLMs? Or is this multiplayer LLM chat?

If there are user rooms and team rooms, then I'd use the teamId as the userId for those chats.
Then do a search in the user's room and a search per team room the user has access to. Then you have fine-grain control.

Or duplicate the message info into another place to do fine-grain search over it - whether that's your own tables, algolia, etc.

potent fog
#

thanks for the ideas

potent fog
#

@thick sigil actually I have one more question is there any way we can directly extend the schema of the chat messages (like just add attributes) or is the only way to add a new table and save the thread id and any other properties we want to it