← All notes

AI Agents

Give the agent its own credentials, scoped down

An agent running with the service account can do anything the service can. The blast radius of a bad tool call is then the whole system.

  • Invexa Technologies
  • 2 min read

Agent tools are usually wired to whatever database handle or API client was already in scope. It is the fastest path to a working demo and it means the model’s output is one function call away from every capability your backend has.

The model is untrusted input

Not malicious — just non-deterministic, and steerable by whatever text lands in its context. A retrieved document, a customer message, a filename in an attachment. Prompt injection is not exotic; it is the expected behaviour of a system that takes instructions from text and then reads text.

Treat every tool call as originating from the least trusted party in the conversation, because it might be.

Scope the credential, not the prompt

Telling the model not to delete things is not a control. The control is that it cannot.

agent_role
  select  on customers  where tenant_id = :tenant
  select  on orders     where tenant_id = :tenant
  insert  on tickets
  -- no update, no delete, nothing else

A separate database role with exactly the permissions the tools require. External APIs get their own key with the narrowest scope the provider offers. If the agent only reads orders, the credential can only read orders, and the worst a compromised prompt achieves is reading orders it was already allowed to read.

Tenant isolation belongs below the tool

The most common serious bug in multi-tenant agent systems is a tool that takes a customer id from the model. The model can produce any id, including a real one belonging to someone else.

Tenant scoping is injected from the authenticated session at the tool boundary — never a model-supplied parameter. If a tool signature accepts tenant_id, that is the bug.

Write actions need a second gate

Reads scoped by credential are usually enough. Writes that move money, send messages, or delete records need an approval step or a hard ceiling — a per-conversation cap on refund value, a confirmation for anything irreversible.

Log the call, not just the conversation

Every tool invocation with its arguments, the resolved credential, and the result:

tool_calls
  conversation_id, tool, arguments, tenant_id
  outcome, latency_ms, called_at

When something goes wrong the transcript tells you what the model said. This tells you what it actually did, which is the only version that matters.

Next step

Have a project in mind?

A 30-minute call is usually enough to know whether we are the right team for it. If we are not, we will say so.

Start a project

Replies within one working day