A production agent is an application that uses a model to decide what to do next. The model is important, but it is only one component. Around it sit instructions, runtime context, tools, identity, policy, state, observability, and a loop that keeps feeding new observations back into the model until the task is complete or the system decides to stop.
That distinction matters because many prototype failures come from treating the LLM as the application. In a demo, it can feel natural to place business rules in the prompt, let the model choose arbitrary API calls, and trust the response text as evidence that an action happened. In production, those shortcuts become reliability and security bugs.
A better mental model is an execution harness. The user provides an objective. The model reasons over the context it is allowed to see. It may request a tool. The runtime validates and executes that request, returns the result, and lets the model reason again. The application—not the model—owns the loop, the identity, the limits, and the side effects.

The boundary that makes agents safe
The model should be able to say, “I believe this customer is asking for a refund.” It should not be able to decide that the customer is authorized, that the order is eligible, that the refund amount is valid, or that the payment system should execute the transaction. Those are deterministic business decisions.
A refund example
Consider a customer who says: “My headphones never arrived. Can you refund me?” A robust agent does not invent the order ID or pass a customer ID supplied by the model. The authenticated application context supplies identity. The model calls a narrow read tool such as get_my_orders(), then a deterministic policy service decides whether the selected order is eligible.
1get_my_orders()2 ↓3check_refund_eligibility(order_id, reason)4 ↓5prepare_refund(order_id, reason)6 ↓7pending_action_id8 ↓9user confirms10 ↓11backend revalidates12 ↓13confirm_refund(pending_action_id)The model handles language, ambiguity, and sequencing. The backend handles identity, policy, amount limits, current state, idempotency, and financial execution. The result is still an agentic experience, but the agent is not the security boundary.
Responses API, agent runtimes, and harnesses
Modern agent stacks increasingly separate the model/tool primitive from the execution harness. OpenAI’s Responses API exposes model responses and tool calling, while the Agents SDK adds higher-level runtime capabilities around agent loops, tracing, handoffs, memory and controlled execution. The architectural lesson is broader than any one SDK: keep the model call separate from the code that owns execution policy.
PFPLabs takeaways
- Agent ≠ model. An agent is a model inside an execution system.
- Authority stays outside the model. Identity, authorization, state, and side effects belong to deterministic services.
- The loop is application-owned. The runtime decides what can execute, how often, and when the agent must stop.
- Narrow capabilities beat arbitrary APIs. A smaller action surface is easier to secure, observe, and evaluate.
