When I first designed an AI agent to manage customer support tickets, I assumed the biggest challenge would be building a robust retrieval system. What I didn’t realize was that the most critical decision I made—how to handle tool-call permissions—would determine whether the system could scale reliably. This is the story of how embeddings are reshaping how we think about trust boundaries in AI systems, and why tool-call permissions matter more than you might expect.
The Embedding Index as a Trust Boundary
Embeddings are often described as the new database index, but this analogy is more than just poetic. Traditional relational databases use indexes to optimize query performance by mapping keys to rows. Embeddings achieve a similar purpose but for semantic similarity: they allow systems to quickly locate relevant information in unstructured or semi-structured data. This makes them ideal for building search systems, but it also introduces a new type of trust boundary.
In an AI agent system, the embedding index becomes the first line of defense against ambiguous or malicious queries. When an agent receives a user request, it must determine which tools to invoke based on the semantic similarity between the query and the indexed data. This is where permissions come in. If the agent is allowed to invoke any tool without restriction, it risks executing unintended actions—whether due to a bug, a misconfigured prompt, or an adversarial input.
The key realization is that the embedding index isn’t just a search mechanism; it’s a trust boundary. The tools the agent can call must be explicitly authorized based on the context of the query and the state of the system. This is a critical design decision that often gets overlooked in early-stage prototypes.
Designing Tool-Call Permissions in AI Agents
A practical approach to managing tool-call permissions is to layer them on top of the retrieval system. Here’s how it might look in code:
interface Tool {
id: string;
name: string;
description: string;
permissions: string[];
}
function canInvokeTool(tool: Tool, context: any): boolean {
// Check if the tool is explicitly authorized for the current context
if (tool.permissions.includes('all')) return true;
// Check if the user has permission to invoke this tool
if (context.userPermissions.includes(tool.id)) return true;
// Check if the tool is allowed in the current state
if (context.state?.allowedTools?.includes(tool.id)) return true;
return false;
}This function enforces a three-tier permission model:
- Tools marked with
allpermissions are always available - Tools explicitly authorized for the user
- Tools allowed based on the current system state
In practice, this means you should never assume a tool is available. Instead, always validate permissions at the point of invocation. This prevents accidental or malicious use of tools that shouldn't be accessible.
The most common pitfall I've seen is when teams treat embeddings as a search mechanism rather than a security boundary. For example, allowing an AI agent to access a database without checking the user's permissions creates a critical vulnerability. The embedding index is just the first step in the process—what happens after the search must be carefully controlled.
Approval Boundaries and Retrying Failed Tool Calls
When a tool call fails, the system must decide whether to retry, escalate, or fail gracefully. This is where approval boundaries become essential. Consider a scenario where an AI agent is trying to update a customer's account information. If the tool call fails due to a network error, the agent should be allowed to retry. But if the failure is due to an invalid request, the system should reject it outright.
The key is to design the system with an explicit approval workflow. For example:
- The agent makes a tool call
- The system validates the call against the current state and permissions
- If validation fails, the system logs the reason and rejects the call
- If validation passes but the call fails, the system decides whether to retry based on the error type
This approach prevents infinite loops and ensures that the system remains in a consistent state. It also makes debugging failures significantly easier, as the system logs both the initial request and the validation outcome.
A common mistake is to allow the agent to retry indefinitely without checking the context. This can lead to situations where the agent keeps making the same invalid call, wasting resources and potentially causing the system to crash. Always include a retry limit and a mechanism to escalate to a human operator when necessary.
Conclusion
Embeddings are more than just a search mechanism—they're a critical trust boundary in AI systems. By treating them as the new database index, we can build more reliable and secure AI agents. The most important lesson I've learned is that tool-call permissions should never be an afterthought. They need to be designed with the same rigor as any other system boundary.
When building an AI agent, always ask: what are the conditions under which this tool should be allowed to run? What happens if it fails? How do we ensure the system remains in a consistent state? These are the questions that will determine whether your AI system is reliable, secure, and scalable.