DEV Community

Cover image for Best practices for implementing LLM access controls and monitoring
RESK
RESK

Posted on

Best practices for implementing LLM access controls and monitoring

The question engineers actually ask

When a team ships an LLM agent, the first security conversation is usually about prompts. The second conversation, the one that matters, is about what the agent is allowed to do once it decides to act.

This article is about that second conversation: access controls and monitoring for LLM driven agents. It assumes you already run an agent in production, or are close to it, and that you have a competent engineer asking where the control belongs.

What is AI agent security

AI agent security is the discipline of constraining and observing an autonomous or semi autonomous system that can call tools, read data and take actions on behalf of a user or a service.

It differs from classic application security in one important way. In a classic application, the set of actions is fixed at build time. In an agent, the set of actions is chosen at runtime by a model, based on context you do not fully control. The model is not an attacker. It is an interpreter of untrusted input that happens to have credentials.

That is the whole problem in one sentence.

The specific question: access controls and monitoring

Best practices for implementing LLM access controls and monitoring come down to three decisions:

  1. Where in the request path does authorization happen.
  2. What identity the decision is made against.
  3. What gets recorded, and what happens to that record.

Everything else is detail.

Attack surface, concretely

Consider an agent with a token that can call a set of tools. A tool might read a document, query a database, send a message or open a pull request.

The failure mode is not exotic. It looks like this: untrusted content enters the context, the model selects a tool that is technically available to the token, and the call executes. Nothing in the request path asked whether this agent, for this user, in this session, should be allowed to call that tool with those arguments.

The token was valid. The tool was registered. The call succeeded. That is the failure.

It is not theoretical because the token is the only thing standing between the model and the tool. If the token is broad, the agent is broad. If the agent is broad, the blast radius is the union of everything the token can reach.

The mechanism that stops it

The mechanism is a policy decision point at the tool invocation boundary.

Ordering matters, and this is where most implementations get it wrong. The correct order is:

  1. The model proposes a tool call.
  2. The arguments are parsed and validated against a schema.
  3. The authorization decision runs against the agent identity, the tool name and the validated arguments.
  4. Only then does the tool execute.

If authorization runs before argument validation, you authorize a string you have not inspected. If it runs after execution, you have written a log, not a control.

The decision itself is a least privilege decision. The agent should hold the narrowest scope that lets it complete its task, and the policy should deny by default. A denied call is not an error to be swallowed. It is a signal.

Monitoring is the other half of the same mechanism. Every decision, allow or deny, should be recorded with the agent identity, the tool name, the arguments that were evaluated and the outcome. Without that record you cannot answer the only question that matters during an incident: what did this agent actually do.

Implementation with RESK

RESK builds this into the agent path rather than around it.

reskSecure is the enforcement layer. It sits at the tool invocation boundary, evaluates the agent identity and the validated arguments against policy, and denies by default. Least privilege is the operating assumption, not an optional mode.

ReskPoints is the observation layer. It records the decisions and the activity around them so that the allow and deny history of an agent is available when you need it, not reconstructed after the fact.

Together they answer the two questions from the top of this article. reskSecure answers where the control belongs. ReskPoints answers what was recorded.

You can read more about the enforcement model at https://resk.fr/projects/resksecure.html

Checklist

  • Authorization runs at the tool invocation boundary, not in the prompt and not in a post execution hook.
  • Argument validation runs before the authorization decision, not after.
  • The decision is made against a specific agent identity, not a shared service token.
  • Policy denies by default and grants the narrowest scope that completes the task.
  • Every allow and every deny is recorded with agent identity, tool name and outcome.
  • A denied call is treated as a signal and reviewed, not silently retried.
  • The token scope is reviewed whenever a new tool is registered.

If you cannot answer where the decision happens in your own request path, that is the first thing to fix.

Top comments (0)