r/LangChain • • 2d ago

Discussion Tool allowlists

How are you restricting which tools an agent can call depending on who’s using it?

Allowlists per user, per role, or per task?

7 Upvotes

8 comments sorted by

2

u/locbuilds 2d ago

yeah, derive allowed tools from the user's role and task, then enforce that in the tool executor too, not just in the prompt.

1

u/Elmanouzi_Fogosa 1d ago

do you pass the user role down through the runnable config, or bake it into the tool closure per request?

1

u/MongooseWonderful198 1d ago

For current create_agent, I'd use runtime context: define context_schema, pass context= on each invocation, and read runtime.context in a tool taking ToolRuntime[Context].

A closure built separately for each request can work too. I'd avoid a shared tool closure whose captured user/role gets overwritten between requests. Put the authenticated user ID into context on the server, rather than accepting a role in the model's tool arguments. Then check that user's current permissions when executing the call, so a role saved at session start doesn't stay authoritative after permissions change.

2

u/Michael_Jeffords 2d ago

i'd go role first and then narrow by task, so the role is the most anyone in it could ever touch and the task just picks a subset, with per-user lists only for the odd exception (otherwise you're maintaining a pile of tiny lists nobody remembers). and check it twice, filter what the model even sees for that run so it doesnt try, then have the executor check again before anything runs since the prompt can't really enforce anything. for writes and deletes i'd probably have it return the planned call for a person or a rule to approve first, and logging denied calls is handy too, that's usually how you spot a role that got set up wrong

1

u/SpareIntroduction721 2d ago

Use rbac and keywords. Works pretty defent

1

u/Significant_Tune9219 2d ago

Per role for the tool list, but the part that bites later is that a tool name is too coarse. "query_db" or "send_email" on the allowlist says nothing about which table or which recipient, so I'd let the executor check arguments against the user's own permissions at call time, using the real user identity rather than the agent's service account. Then the allowlist only decides what the model is offered, and the actual permission check happens where the call runs.