I am not against agents. I am against using agents to hide missing APIs, missing automation, and messy data ownership. When teams start agent first, the demo can look magical, but the production design usually becomes a pile of brittle shortcuts.
The risk is not that the agent is smart. The risk is that the agent gets access to systems through paths that nobody designed, reviewed, observed, or owned.
The shortcut I do not trust
I have seen the temptation: give the agent database access, a few internal pages, a browser session, and a prompt that says "be careful." It feels fast because the first demo skips the hard engineering work.
That shortcut creates hidden risk. The agent may read data the user should not see, combine stale data with current policy, bypass audit trails, or take an action through a screen flow that was never meant to be automated. Worse, every failure becomes hard to explain because nobody knows whether the bug came from the model, the prompt, the data, the page scrape, or the missing business rule.
The order I prefer
I start with APIs because APIs define the safe surface area. A good API says who can ask, what they can ask for, what validation applies, what response shape is allowed, and what gets logged. The agent should not invent access. It should call an approved capability.
I put automation next because a suggested action is not enough. If a support credit, invoice correction, access approval, or deployment rollback matters, I want a workflow that is idempotent, observable, retryable, and owned by a team. The model can recommend. The automation should execute.
Then I deal with data. I want ownership, freshness, lineage, permission, and confidence. My enterprise knowledge systems article goes deeper on this point: retrieval without trust metadata is not a knowledge system. It is a search box with better wording.
The stack I want before the agent
A practical example I would use
Take a customer support agent that helps with billing complaints. The unsafe version gives the agent access to invoice tables, CRM notes, policy documents, and maybe a browser workflow to issue a credit. The agent can sound confident, but it may use the wrong region policy, ignore a contract exclusion, or create a credit without a clean audit trail.
The safer version is boring in the best way. The agent calls one customer context API. That API checks entitlement, pulls the current invoice, reads the active policy, checks freshness, and returns allowed actions with evidence. If a credit is possible, the agent opens a recommendation. The actual credit runs through a separate automation workflow with approval and idempotency.
The API should make unsafe access impossible
from datetime import datetime, timezone
from fastapi import FastAPI, Depends, HTTPException
from pydantic import BaseModel
app = FastAPI()
MAX_STALENESS_SECONDS = 300
class AgentContextRequest(BaseModel):
customer_id: str
product: str
region: str
actor: str
class AgentContext(BaseModel):
customer_id: str
invoice_status: str
policy_version: str
freshness_seconds: int
allowed_actions: list[str]
evidence: list[str]
@app.post("/agent/customer-context", response_model=AgentContext)
def customer_context(req: AgentContextRequest, user = Depends(current_user)):
if not can_view_customer(user, req.customer_id, req.region):
raise HTTPException(status_code=403, detail="customer is not visible")
invoice = billing_store.latest_invoice(req.customer_id)
policy = policy_store.active_policy(req.product, req.region)
age = int((datetime.now(timezone.utc) - invoice.loaded_at).total_seconds())
if age > MAX_STALENESS_SECONDS:
raise HTTPException(status_code=409, detail="billing data is stale")
allowed = []
if invoice.status == "overcharged" and policy.refund_allowed:
allowed.append("recommend_credit")
return AgentContext(
customer_id=req.customer_id,
invoice_status=invoice.status,
policy_version=policy.version,
freshness_seconds=age,
allowed_actions=allowed,
evidence=[
f"invoice:{invoice.id}",
f"policy:{policy.version}",
f"actor:{req.actor}"
]
)
This is the kind of API I want an agent to use. It does not expose raw tables. It checks user access, rejects stale billing data, applies the active regional policy, and returns only the actions the agent is allowed to recommend. The evidence list gives support, audit, and review teams a trail to inspect later.
How I stop the madness
I do not start by asking, "What can the agent do?" I start by asking, "What capability are we willing to expose safely?" That changes the conversation. The team has to name the owner, the input contract, the data sources, the freshness rule, the permission model, the audit record, and the rollback path.
I also separate recommendation from execution. Agents are good at gathering context and proposing a next step. Production systems still need deterministic workflows for actions that change money, access, inventory, deployments, or customer state. That is the same reason I like clear workflow boundaries in agentic application architecture and clear packaging boundaries in skills versus plugins.
My simple rule
If the agent needs a hack to reach the data, the data product is not ready. If the agent needs a screen scrape to take action, the automation is not ready. If nobody owns the API, the agent is not ready.
API first gives the agent a safe door. Automation first gives the business a repeatable action. Data first gives the answer a reason to be trusted. Agent first should come after that foundation, not before it.