An assistant that can choose tools is appealing. But flexible tool selection also creates more paths through a process. Before deciding on an agent architecture, write down the work and its exceptions.
Separate three kinds of decisions
Consider an incoming request to update a customer record. The process might require reading a message, identifying the requested change, checking the customer account, and applying an update.
These steps have different needs:
| Step | Useful starting point | Why |
|---|---|---|
| Validate a customer ID | Fixed logic | The accepted format is explicit. |
| Interpret a free-text request | Language-model extraction, evaluated on examples | Wording varies. |
| Confirm authorization | Application access controls | A model output is not evidence of permission. |
| Apply a consequential update | Validated tool, with approval where needed | The action changes a system of record. |
This is a workflow with a language step. It does not necessarily require an agent to plan the whole process.
Make the action boundary explicit
The following runnable Python example illustrates a fixed validation boundary. It is deliberately small: it is not a production authorization system.
from dataclasses import dataclass
@dataclass(frozen=True)
class Proposal:
customer_id: str
field: str
value: str
def validate(proposal: Proposal) -> None:
if not proposal.customer_id:
raise ValueError("Missing customer ID")
if proposal.field not in {"preferred_language"}:
raise ValueError("Field is outside the permitted scope")
if proposal.value not in {"en", "cs"}:
raise ValueError("Unsupported language")
proposal = Proposal("customer-123", "preferred_language", "cs")
validate(proposal)
print("Valid proposal; authorization and approval are still required.")
The validation checks structure and scope. A separate application layer must confirm that the requester can access the customer, that the change is allowed, and that any required approval is genuine. A model must not be able to manufacture that approval by placing a flag in its own output.
Design for failures before expanding autonomy
For each tool, define what happens when it times out, receives incomplete input, or succeeds while the caller loses the response. A retry of a write can duplicate an action unless the receiving system supports an appropriate idempotency mechanism.
Record enough context to explain an execution: the request, validated inputs, tool result, and approval event. Avoid collecting sensitive content just because it is convenient to log everything.
Evaluate the process, not just the response
Use representative requests, ambiguous instructions, missing records, and deliberate attempts to exceed the action scope. Measure whether the system chose the permitted action and whether it stopped when evidence or authorization was missing.
An agent becomes a reasonable candidate when the order of work varies and the available tools can be bounded safely. Even then, stable steps can remain deterministic.
References
-
Anthropic: Building effective agents, published 19 December 2024, distinguishes predefined workflows from model-directed agents. The distinction is useful for the design decisions discussed here.
-
OWASP: Prompt Injection describes how untrusted content can influence model behavior. Treat retrieved documents and tool outputs as data rather than a source of application permissions.