by AgentPolicy (LX AI)

Allowed tools vs open-ended agents

The appeal of an open-ended agent is real: give it a shell, a browser, and a mailbox, and it can solve problems you did not script. The cost is blast radius. Every tool you add is a path an injected instruction can travel. The design question is not whether to grant capability, but how to grant it narrowly enough that a wrong step stays contained.

Least-privilege tool definitions

I start by writing a tool contract that states exactly what the agent may do and what it may not. A “read ticket” tool should expose only a GET operation on a specific ticket identifier, with no ability to mutate the ticket, attach files, or call other endpoints. A “send email” tool should accept only a predefined recipient list, a fixed subject line template, and a body that is sanitized for newline injection. By narrowing the contract, a single mistake in the model’s output becomes a bounded event instead of a cascade.

Define the verb set

List every HTTP method, database command, or file operation the tool needs. If the tool only needs to read, omit POST, PUT, DELETE, and any administrative commands. I keep a spreadsheet that maps each tool name to the allowed verbs and I review it whenever a new endpoint is added.

Constrain arguments

For each argument I specify a type, a length limit, and an allowed character set. A ticket ID might be a UUID, limited to 36 characters. A file path might be restricted to a subdirectory under /var/agent/data and must not contain “..” or absolute paths. I use a schema validation library that rejects any request that does not conform before the tool runs.

Version the contract

I store the tool definition as a JSON file in version control. Any change triggers a pull request that requires sign‑off from a security reviewer. This creates an audit trail that shows when the privilege surface was expanded and why.

To see how prompt injection can abuse overly broad tools, review the OWASP LLM01 guidance: https://genai.owasp.org/llmrisk/llm01-prompt-injection. The cheat sheet shows concrete examples where a model was tricked into invoking a shell command because the tool accepted unrestricted input.

Tool name | Allowed verb | Argument constraints | Example safe call read_ticket | GET | ticket_id: UUID, 36 chars | /tickets/123e4567-e89b-12d3-a456-426614174000 send_email | POST | to: list from approved_domains, subject: max 78 chars, body: sanitized | {"to":["user@example.com"],"subject":"Update","body":"Please review the attached report."} list_files | GET | path: must start with /var/agent/data/, no “..” | /var/agent/data/logs/2024-09-01.txt

Confirmation on irreversible actions

Actions that change state outside the agent’s sandbox—such as sending a message, deleting a record, or deploying a build—must be gated by a separate approval step that the agent cannot invoke on itself. I treat these as one‑way doors and design the policy to require a human token or a short‑lived approval service before the tool executes.

Separate approval endpoint

I expose an internal API that accepts a signed request from the agent, logs the request, and then waits for a human to click “approve” in a UI or respond to a chat command. The agent receives only a pending identifier; it cannot poll the approval endpoint to force a grant.

Time‑bound tokens

When approval is granted, the system issues a token that is valid for a single use and expires after five minutes. The tool endpoint checks the token’s signature and expiration before proceeding. If the token is missing or stale, the tool returns an error and the attempt is logged.

Logging the gate

Every approval request and decision is written to an immutable log with timestamps, the agent’s identifier, the tool name, and the arguments that were presented. This log lets me reconstruct whether a poisoned instruction managed to bypass the gate or was stopped at the approval step.

For guidance on securing credential hygiene in automated pipelines, see the OWASP CI/CD security risk sheet: https://owasp.org/www-project-top-10-ci-cd-security-risks/CICD-SEC-06-Insufficient-Credential-Hygiene. It reinforces the principle that secrets should never be stored in a place where an agent can read them without an explicit approval flow.

Audit logs as a control, not an afterthought

I treat the audit log as the primary evidence that a policy is being enforced. Without a reliable log, statements about least privilege are unverifiable claims. I design the logging layer to be write‑only from the agent’s perspective and to be stored in a system that the agent cannot alter or delete.

What to log

- Timestamp with millisecond precision - Agent identifier (model version, deployment ID) - Tool name and the exact verb called - All arguments passed to the tool, after validation - Result status code and any returned data summary (size, not full content) - Source of the request (user‑initiated, scheduled trigger, or policy‑engine)

Storage guarantees

I write each log entry to an append‑only store such as a write‑ahead log in a cloud storage bucket with object versioning enabled. The bucket policy denies any delete or overwrite operation from the agent’s service account. This ensures that even if the model is compromised, the history remains intact.

Querying for investigations

When an incident is reported, I run a simple SQL‑like query against the log index to find all runs of a particular tool within a time window. I avoid complex joins that could be slow; instead I rely on partitioned tables by date and tool name. The query returns the list of identifiers that I then pull for deeper forensic analysis.

To understand how input validation can prevent malicious arguments from reaching a tool, consult the SQL injection prevention cheat sheet: https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html. The sheet shows parameterized queries and strict typing, which mirror the argument‑validation approach I use for agent tools.

When open-ended access is justified

There are legitimate cases where an agent needs broader reach, such as exploratory data analysis or threat‑hunting in a isolated environment. In those situations I grant openness only after I have placed the agent in a sandbox that blocks any path to production data or external payment systems.

Sandbox boundaries

The sandbox provides a shell, a browser engine, and a mailbox that can only send messages to a dedicated test domain. Network policy blocks outbound traffic to any IP address that belongs to the company’s internal CIDR ranges. Egress is allowed only to a set of approved public mirrors for package installation.

Credential isolation

No production secrets are mounted into the sandbox filesystem. Instead, the agent receives a temporary token that can read from a public dataset bucket. If the agent attempts to read a file outside the allowed mount point, the kernel returns a permission error and the attempt is logged.

Time‑boxed sessions

Each sandbox session lasts a maximum of two hours. After the timeout, the environment is torn down and a fresh image is launched. This limits the window during which a misbehaving agent could explore or exfiltrate data.

I still apply least‑privilege tool definitions inside the sandbox; the difference is that the consequences of a mistake are contained to the disposable environment rather than to production systems.

Treat generated policies as drafts

When a model or a junior engineer produces a policy file, I review it exactly as I would review untrusted code that is about to be deployed to a critical service. The review checklist includes verifying each rule against the actual tool definitions, confirming that deny paths exist, and ensuring the file is versioned.

Rule‑to‑tool mapping

I create a spreadsheet that lists every tool on one axis and every policy rule on the other. For each cell I mark whether the rule permits, denies, or is silent on the tool’s operation. Any silent cell triggers a comment that asks the author to clarify intent.

Deny‑by‑default check

I run a static analysis script that attempts to invoke each tool with a set of malformed arguments. If the script finds a combination that the policy allows but that should be denied (for example, a “delete” tool accepting a wildcard identifier), the script fails the build and the policy must be revised.

Version control and review

The policy file lives in a Git repository with branch protection that requires two approvals before merging. I tag each released version with a semantic number (e.g., v1.2.0) and attach the corresponding tool definition snapshot. This makes it possible to roll back to a known‑good state if a new version introduces an over‑permissive rule.

I never consider a generated policy to be final until it has passed this review cycle. A policy that is never examined creates a false sense of safety and can hide gaps that only appear under real‑world load.

What this is NOT

This guide does not promise that following the steps will eliminate every possible failure mode. I do not claim 100 % protection against prompt injection, credential leakage, or logic errors. I also do not state that an agent will never miss a malicious instruction; detection depends on the quality of logs, the timeliness of human review, and the correctness of the tool contracts. Treat the patterns as risk‑reduction measures, not as a guarantee of absolute safety.

Related articles

- AI agent policy packs through a NIST AI RMF lens - Explore the full AI micro-SaaS topic matrix →

Is an open-ended agent always a bad idea?

No. Broad reach is justified for research or triage inside a sandbox with no production credentials and no external egress. The rule is to earn openness with isolation rather than grant it by default.

What is the single most important tool control?

Confirmation on irreversible actions such as send, delete, transfer, and deploy. A gate the agent cannot trigger itself breaks the chain from a poisoned instruction to an external effect.

Why are audit logs part of the policy?

Logs prove which tools ran and with what arguments. Without them, least-privilege is a claim you cannot verify, and an incident becomes impossible to reconstruct.

Should I trust a generated policy pack as written?

Treat it as a draft. Verify each rule against the real tool definitions, confirm the deny paths exist, and version the result. A policy never read is worse than none, because it implies coverage that is not there.

Decision-support only. Not legal advice or a compliance certificate.

← Back to blog · Read full English article

Was this result helpful?Feedback