ShieldThemes Web Development
+1 (415) 555-0142 Get a quote →
← Journal/AI

Giving AI agents tool access without handing over the keys

Scoped credentials, server-side policy, confirmation steps and prompt-injection defenses for agents that can take real actions in your systems.

Daniel Reyes
Daniel Reyes
Lead AI Engineer · Oct 15, 2025 · 5 min read
Giving AI agents tool access without handing over the keys

An AI agent that can only read and suggest is useful. An agent that can issue refunds, update records and send emails is far more useful, and it is also a new kind of user in your systems, one that can be persuaded by any text it reads. The engineering question is not whether the model is trustworthy. It is how to design the system so that it does not need to be. These are the controls we put around every agent that takes real actions.

Treat the model as an untrusted client

The core principle is simple. Every tool call an agent makes should be handled as if it came from an anonymous request on the public internet, because in effect it did. Any document, email, web page or ticket the agent reads can contain instructions, and models follow instructions. Prompt injection has no complete fix at the model layer, so the defenses have to live in the code around it.

In practice that means the prompt describes what the agent should do, while your server decides what it can do. If the only thing stopping an agent from refunding $10,000 is a sentence in its system prompt, the system has no limit.

The system prompt is guidance. The API is the policy. Never confuse the two.

Scope tools narrowly

The most effective control is giving the agent fewer, smaller capabilities. Instead of a general "call the billing API" tool, expose specific actions with constrained parameters:

  • Task-shaped tools. "Extend trial by up to 14 days" rather than "update subscription." The narrower the tool, the smaller the damage from misuse.
  • Bound to the current context. Tools act only on the customer or record the conversation is about. The agent never passes an arbitrary account ID; the server injects it from the authenticated session.
  • Read and write separated. Read tools are broad enough to be useful; write tools are few and individually justified.
  • Dedicated credentials. The agent's service account has only the permissions its tools need, can be revoked in one step, and appears clearly in every audit log.

We ask one question about every proposed write tool: if an attacker controlled every argument, what is the worst outcome? If the answer is unacceptable, the tool needs tighter limits, a confirmation step, or should not exist.

Enforce policy on the server

Each write tool validates its arguments against business rules before doing anything. Limits on amounts, frequency and eligibility are checked in code, and violations are refused and logged rather than silently corrected. A simple pattern looks like this:

def apply_credit(session, amount_cents, reason):
    customer = session.customer  # from auth, never from the model
    if amount_cents <= 0 or amount_cents > 2500:
        return refuse("amount_out_of_policy")
    if credits_last_30_days(customer) >= 1:
        return refuse("frequency_limit")
    return ledger.credit(customer, amount_cents, reason, actor="agent")

Refusals are returned to the agent as structured errors so it can explain to the user or escalate. They are also counted; a spike in refusals is often the first sign of an injection attempt or a prompt regression.

Confirmation, rate limits and kill switches

Some actions are too consequential for autonomy but still worth automating the preparation. For those we use a confirmation step, where the agent drafts the action and a human or the end user approves it:

  1. Actions above a monetary threshold go to a staff approval queue with the agent's reasoning attached.
  2. Irreversible customer-facing actions, such as cancelling a subscription or deleting data, require the customer to confirm through a button rendered by the application, not a typed reply the agent interprets.
  3. Outbound messages to anyone other than the current user, such as emails to third parties, are drafted but never sent autonomously.

On top of that, every agent has per-tool rate limits, a maximum number of actions per conversation, and a feature flag that disables write tools instantly while leaving read-only help available. We test the kill switch before launch, because a switch nobody has flipped is a switch nobody trusts.

Defending against prompt injection

You cannot prevent a model from reading hostile text, but you can limit what that text achieves. Beyond narrow tools and server-side policy, we apply a few specific measures:

  • Clearly delimit untrusted content in the prompt and tell the model it is data, which reduces but does not eliminate risk.
  • Never let content retrieved from external sources trigger write tools in the same step without a policy check tied to the authenticated user.
  • Strip or neutralize links and hidden text from retrieved documents where they are not needed.
  • Prevent data exfiltration by disallowing tools that fetch arbitrary URLs or render images from untrusted domains.
  • Include injection attempts in the evaluation set and treat any successful one as a release blocker.

Log everything, review some of it

Every tool call is logged with the conversation ID, arguments, policy decision, result and model version. Those logs feed three things: an audit trail for compliance, a daily sample for human review, and the evaluation set, which grows every time a reviewer spots a bad action. When something goes wrong, and eventually something will, you want to reconstruct exactly what the agent saw and did in minutes, not days.

This is how we build every custom AI agent, and the same controls apply when we connect models to internal systems through LLM integration work. For clients in regulated industries, we pair agent launches with a focused security audit that includes adversarial testing of the tools.

Plan a safe rollout

If you are considering an agent that can take actions in your systems, start with a list of the actions and the worst case for each. Send that list to us and we will propose the controls, the rollout plan and a fixed price within a day.

Daniel Reyes
WRITTEN BY
Daniel Reyes
Daniel builds production AI agents for support, sales and operations teams. Before ShieldThemes he worked on search ranking systems.
All articles by Daniel Reyes →
Want this on your project?
Get a fixed-price quote from a senior lead within 24 hours.
Request a quote →

Keep reading

How we shipped a support agent that resolves 62% of tickets
AI · 5 min
How we shipped a support agent that resolves 62% of tickets
What to learn in the two weeks before a website redesign
Design · 5 min
What to learn in the two weeks before a website redesign
Migrating to Shopify Plus without losing a single ranking
Shopify · 5 min
Migrating to Shopify Plus without losing a single ranking