AI agents are starting to change the assumptions behind commerce software.
For a long time, ecommerce platforms were designed around human interpretation. A product page could contain a mixture of structured data, marketing copy, policy fragments, trust signals, pricing information, availability indicators, and checkout calls to action. A human user could interpret that mixture well enough to make a decision.
That model does not transfer cleanly to agentic commerce.
When an AI agent interacts with a commerce system, ambiguity becomes a system-design problem. The agent should not need to infer whether a product can be recommended, whether inventory is fresh, whether a policy applies, whether checkout is allowed, or whether payment authority exists. Those decisions need to be represented explicitly by the platform.
This article is the first in a technical series about designing an agent-ready commerce platform. The focus is not on adding a chatbot to an ecommerce UI. The focus is on the lower-level architecture required when external agents, tools, and protocols need to interact with commerce workflows safely.
Traditional ecommerce platforms expose experiences primarily through pages and user-driven flows:
Product page → Cart → Checkout → Payment → Order
That flow assumes a human is driving the process. The platform presents information, the user interprets it, and the user decides what to do next.
Agentic commerce introduces a different interaction model. A system may need to answer questions such as:
These are not only API design questions. They are domain modeling questions.
A more useful mental model for agent-ready commerce is:
Facts → Eligibility → Authority → State transition → Evidence → Audit
This model is less familiar than the page-based ecommerce flow, but it captures the main architectural shift. A commerce platform that interacts with agents must expose more than products and endpoints. It must expose the conditions under which commercial actions are valid.
A common first step is to expose a structured product feed. That is necessary, but incomplete.
A basic product record might look like this:
type Product = {
id: string;
name: string;
price: number;
currency: string;
inStock: boolean;
};
This structure is useful for rendering a storefront or indexing a catalog. It is not enough for an agent deciding whether a product can be recommended, compared, added to cart, or used in a checkout flow.
The missing layer is commercial truth: the platform’s current, source-backed understanding of the product as a commercial object.
For example:
type ProductTruthSummary = {
productId: string;
priceFreshness: "fresh" | "stale" | "unknown";
inventoryFreshness: "fresh" | "stale" | "unknown";
policyCoverage: "complete" | "partial" | "missing";
sourceStatus: "verified" | "changed" | "unverified";
agentVisible: boolean;
};
This structure separates raw product data from the confidence and completeness required to use that data in agent-facing decisions.
A product may exist in the catalog but still be unsuitable for agent discovery. A product may be discoverable but not checkout-ready. A product may be checkout-ready but not eligible for delegated payment. A product may have a fresh price but stale inventory. A product may have valid inventory but missing return-policy coverage.
A human can often work around those inconsistencies. An agent should not have to.
This is the first major design principle in agent-ready commerce:
Do not ask agents to infer commercial truth from presentation surfaces.
Expose commercial truth directly.
Many ecommerce systems use product availability as a broad gate. The product is active, in stock, and therefore available.
That approach breaks down once agent actions become more specific.
Consider a simple implementation:
function canCheckout(product: Product) {
return product.active && product.inStock;
}
This function answers a narrow question, but the platform usually needs to answer several different questions:
These actions do not have the same risk profile. Treating them as one availability decision makes the model too coarse.
A more explicit action model is easier to reason about:
type AgentCommerceAction =
| "discover"
| "compare"
| "quote_policy"
| "add_to_cart"
| "prepare_checkout"
| "delegate_payment";
Each action can then produce its own decision:
type ActionEligibilityDecision = {
productId: string;
action: AgentCommerceAction;
allowed: boolean;
blockers: Array<{
code: string;
severity: "info" | "warning" | "blocker";
message: string;
nextAction: string;
}>;
};
The important part is not the exact TypeScript shape. The important part is the separation of concerns.
A product can be safe to discover but unsafe to purchase. It can be safe to compare but unsafe to quote because policy facts are incomplete. It can be safe to prepare checkout but unsafe for delegated payment because payment authority has not been established.
This creates a more reliable interface for agents and a more useful operational model for merchants.
Instead of returning a generic rejection, the platform can return a reason:
Product is discoverable but checkout is blocked because inventory freshness is stale.
That kind of response is useful to both the agent and the operator. The agent knows not to proceed. The operator knows what to fix.
Policy text is another area where human-first assumptions leak into the system.
A human can read a returns page and interpret whether a product is likely covered. An agent should not rely on free-text interpretation when quoting commercial terms.
Policy data needs to be connected to products, categories, markets, and actions.
A simplified policy fact might look like this:
type PolicyFact = {
policyType: "returns" | "shipping" | "warranty" | "cancellation";
appliesTo: {
productIds?: string[];
categoryIds?: string[];
region?: string;
};
status: "known" | "missing" | "stale" | "conflicting";
summary: string;
sourceRef: string;
lastVerifiedAt: string;
};
This gives the platform a way to distinguish between several conditions that would otherwise collapse into vague policy text:
The distinction matters because an incorrect policy claim is not just a technical bug. It can become a customer-support issue, a trust issue, or a compliance issue.
Agent-ready systems therefore need to treat policy facts as part of the commerce domain, not as static content attached to the storefront.
Agent-commerce platforms are likely to interact with multiple external protocol surfaces. Some protocols focus on product discovery. Some focus on tool use. Some focus on checkout or payment authority. Some may be specific to a marketplace, assistant, payment provider, or agent runtime.
A common architecture mistake is to let each protocol adapter make its own business decisions.
For example:
ACP route decides checkout eligibility
MCP tool decides product visibility
Payment adapter decides mandate validity
Admin UI calculates its own issue status
Feed publisher calculates another version of availability
That structure may work temporarily, but it tends to create contradictions. One surface says the product is available. Another says it is blocked. The admin UI shows a third status. The feed publisher uses a fourth rule.
A safer architecture keeps adapters thin:
External protocol
↓
Protocol adapter
↓
Internal domain command/query
↓
Commercial decision service
↓
Protocol-specific response
The adapter translates between external protocol shape and internal domain shape. It should not own the core decision.
This separation is especially important while agent-commerce protocols are still evolving. If the domain model is independent from the protocol adapter, new protocol versions can be supported without rewriting the business rules.
The platform can then maintain one internal answer to questions such as:
Multiple protocols can expose that answer in different formats, but the decision remains owned by the domain.
Checkout is often presented as a button in the UI, but backend systems already know that checkout is a lifecycle. Agentic commerce makes that lifecycle more explicit.
A checkout session may need to pass through several states:
type CheckoutState =
| "draft"
| "validated"
| "awaiting_human_confirmation"
| "payment_authorized"
| "payment_captured"
| "completed"
| "cancelled"
| "expired"
| "blocked";
Each transition has conditions. A draft session should not become validated unless prices, inventory, and policy constraints have been checked. A session should not move into payment authorization unless the required authority exists. A completed session should usually be terminal. A repeated command should be handled safely.
A transition record makes the lifecycle auditable:
type CheckoutTransition = {
from: CheckoutState;
to: CheckoutState;
actor: "human" | "agent" | "system";
reason: string;
evidenceRefs: string[];
occurredAt: string;
};
The key design point is that agents should not be allowed to move commerce state arbitrarily. They should submit commands, and the platform should decide whether the requested transition is valid.
That decision depends on facts, eligibility, authority, and current state.
This makes checkout a good example of the broader architecture pattern:
Agent request → Command validation → Authority check → State transition → Evidence record
Payment authority is one of the areas where vague models become dangerous.
In a human-driven checkout flow, the user typically sees the final cart and authorizes payment directly. In an agent-driven or agent-assisted flow, the platform must be more precise about what authority the agent has.
A boolean such as paymentAllowed
is not expressive enough.
A delegated payment flow needs boundaries:
type PaymentMandate = {
mandateId: string;
sessionId: string;
maxAmount: number;
currency: string;
merchantId: string;
allowedProductIds: string[];
cartSnapshotHash: string;
expiresAt: string;
requiresHumanConfirmation: boolean;
revokedAt?: string;
};
A payment attempt can then be evaluated against the mandate:
type PaymentAuthorityDecision = {
allowed: boolean;
amountWithinLimit: boolean;
currencyMatches: boolean;
merchantMatches: boolean;
productScopeMatches: boolean;
cartSnapshotMatches: boolean;
mandateNotExpired: boolean;
mandateNotRevoked: boolean;
humanConfirmationSatisfied: boolean;
};
This separates payment execution from payment authority.
Calling a payment provider is one part of the system. Proving that the payment attempt is still within the authority granted to the agent is another part.
The second part is where much of the design complexity lives.
Agent-driven systems must assume retries.
A request can time out after the backend has already completed the operation. An agent may retry a command because it did not receive the previous response. A payment command may be submitted twice. A checkout mutation may be replayed.
Idempotency is therefore not just an implementation detail. It is part of the safety model.
A command needs identity:
type AgentCommand = {
commandId: string;
idempotencyKey: string;
actorId: string;
actorType: "human" | "agent" | "system";
action: string;
payloadHash: string;
requestedAt: string;
};
The platform should be able to answer:
This is especially important for payment and checkout operations, where duplicate execution can create real financial or operational damage.
As the backend becomes more explicit, the internal state can become large: product facts, policy facts, feed health, checkout transitions, payment authority, protocol responses, signed writes, request ledgers, attribution records, privacy rules, and audit trails.
Exposing all of that directly to operators usually creates a poor admin experience.
Operators need decisions and tasks, not a raw map of internal subsystems.
A task-oriented view is usually more useful:
type MerchantTask = {
owner: "catalog" | "policy" | "checkout" | "payment" | "operations";
status: "healthy" | "needs_attention" | "blocked";
issue: string;
nextAction: string;
fixImpact: string;
sampleRefs: string[];
};
The task model translates system state into operational work:
Inventory freshness is stale for 12 agent-visible products.
Checkout is blocked until the catalog source is revalidated.
That is more useful than exposing five different internal panels and expecting the operator to infer the business impact.
The admin UI should not leak the architecture unless the user needs to debug at that level. The default view should help the operator answer three questions:
What is wrong?
Why does it matter?
What should be fixed next?
AI-assisted store creation introduces a related problem.
Generating storefront content is not difficult. Generating commercially safe storefront content is harder.
A model can produce product descriptions, category pages, policy summaries, promotional text, and landing-page copy very quickly. But generated content should not automatically become commercial truth.
The platform needs to distinguish between generated content and approved claims.
For example:
type GeneratedCommerceClaim = {
claim: string;
claimType: "product" | "policy" | "shipping" | "warranty" | "promotion";
grounded: boolean;
sourceRefs: string[];
requiresReview: boolean;
publishBlocked: boolean;
};
This prevents a generated storefront from publishing unsupported statements such as:
The same principle appears again: AI output should not become business authority automatically. It should be grounded, reviewed, and published through explicit rules.
Agent-ready commerce adds more concepts to the platform. Without clear boundaries, those concepts can easily become scattered across routes, clients, UI components, protocol adapters, and helper files.
That creates a maintainability problem.
If product eligibility is calculated in one API route, policy coverage in a frontend component, checkout authority in a payment adapter, and agent visibility in a feed publisher, the system will eventually contradict itself.
The architecture needs clear ownership:
apps/
api/
admin-web/
storefront-web/
packages/
commercial-domain/
catalog-domain/
commerce-flow-domain/
protocol-registry/
api-client/
The specific folder names matter less than the ownership rule:
Domain packages own business decisions.
Protocol adapters translate decisions.
UI surfaces render decisions.
This is especially important in an AI-assisted development environment. Code is becoming easier to generate, which means duplication and architectural drift can happen faster. The limiting factor is not only implementation speed. It is the ability to keep the system coherent as it grows.
This first article defines the main architectural problem: agent-ready commerce requires platforms to expose facts, eligibility, authority, state transitions, evidence, and operational tasks explicitly.
The rest of the series will go deeper into each area:
The series is not intended to define a universal standard. Protocols, payment models, and agent runtimes are still evolving. The goal is to document the system boundaries that become important once AI agents are treated as real commerce actors rather than as chat interfaces attached to existing flows.
Agent-ready commerce is not primarily a UI problem. It is not solved by adding an assistant to a storefront, and it is not solved by exposing a product feed alone.
The deeper challenge is architectural.
Commerce platforms need to make hidden assumptions explicit: product truth, policy coverage, action eligibility, checkout state, payment authority, mutation safety, generated-claim review, and operator remediation.
Human users can tolerate ambiguity in ways that agents should not be expected to. If agents are going to discover products, compare options, prepare checkout, or act within delegated authority, the platform needs to expose the rules of commerce in a form that software can evaluate.
That is the core idea behind agent-ready commerce:
Pages are for human interpretation.
Contracts are for machine action.
The rest of this series will examine what those contracts look like in practice.
Written by Dimitrios S. Sfyris, Founder & Software Architect at AspectSoft.
AspectSoft designs and develops custom software platforms, e-commerce systems, SaaS infrastructure, integrations, analytics tools, and practical digital products.
You can also follow the AspectSoft LinkedIn page for updates on software platforms, commerce systems, AI tooling, and developer-focused products.