Digital Commerceby Lisa Dlima

Most ecommerce demos start with a request like “find me a pair of shoes in size 8.” That hides the hard part of digital commerce. Sometimes the buyer is a startup, the cart is a bill of materials, and the purchase is a tiny passive component that can stop an entire hardware build.

Consider the multilayer ceramic capacitor, or MLCC. It disappears into the background until it becomes the reason a production line stops. Mounted on a printed circuit board assembly, an MLCC can stabilize a voltage rail, filter high-frequency noise, or supply short bursts of current near an integrated circuit. An EIA 0603 package measures about 1.6 mm × 0.8 mm, and if that exact capacitor is unavailable, the board may not ship.

That is the purchasing problem I wanted to explore: can an AI help a company reason through a constrained engineering purchase without violating electrical, manufacturing, supply-chain, or payment requirements?

Digital commerce demo input screenThe app starts with a bill of materials, engineering policies, and a UCP-enabled merchant.

The MLCC procurement problem

In this demo scenario, a startup needs high-capacitance MLCCs for a production run. The target part is synthetic, but the constraints are realistic:

bom = [dict(
    part='high-capacitance MLCC', reference_designator='C147', qty=30000, nominal_capacitance_uf=47,
    tolerance_pct=20, min_rated_voltage_v=6.3, operating_voltage_v=3.3,
    min_effective_capacitance_uf_at_operating_voltage=20, package='0603', allowed_dielectrics=['X6S','X7R'],
    required_temp_min_c=-40, required_temp_max_c=105, packaging='tape-and-reel')]

There are also engineering policies:

policies = """
The package must be exactly EIA 0603 because the PCBA layout cannot be changed for this production run.
Prefer X7R over X6S when both are compliant.
Parts must be purchased through an authorized distributor with manufacturer traceability.
RoHS compliance is required.
All parts must ship within 21 days.
Reject any supplier lacking a published payment handler.
Do not automatically substitute a lower capacitance, lower voltage rating, different package, or unapproved dielectric.
Escalate those changes for electrical engineering review.
"""

A normal product search returns “similar” parts, and in hardware “similar” can be dangerous. A lower voltage rating, a different package, or a different dielectric may need electrical review. Even a capacitor with the right nominal capacitance may not provide enough effective capacitance at the operating voltage, because MLCCs derate under DC bias. So the buyer agent cannot optimize for price and availability alone. It has to reason about engineering constraints.

Why this is a good test case

MLCCs combine several hard problems at once:

  • Electrical: capacitance, voltage rating, dielectric, temperature range, effective capacitance under bias
  • Mechanical: the package must match the board layout
  • Manufacturing: packaging format, reel quantity, production quantity, traceability
  • Supply chain: lead time, authorized distributor status, shortage risk
  • Compliance: RoHS, manufacturer traceability
  • Payment: the supplier needs a published payment handler the purchasing agent can use

What the buyer wants is a compliant purchasing decision, and that is where agentic commerce gets interesting.

What I built

I built a small prototype around the Universal Commerce Protocol, or UCP, an emerging protocol for agentic commerce. It gives merchants, platforms, agents, and payment providers a common way to describe commerce capabilities: discovery, catalog search, checkout, payment handlers, and order status.

UCP is protocol-shaped rather than Python-shaped, so I wrote a small helper library called fastUCP to make it easier to use from Python. Instead of manually fetching profiles, inspecting JSON, checking capabilities, and calling raw endpoints, an agent can write:

ucp = UCPClient('https://merchant.example')
profile = ucp.discover()

if ucp.has_capability('catalog.search'): res = ucp.search_catalog(query)

if ucp.has_capability('checkout.create'): checkout = ucp.create_checkout(items)

```

That abstraction lets the rest of the demo focus on the commerce flow rather than HTTP plumbing. For developer relations it is also the point: a protocol is easier to adopt when developers can try it quickly and build something real before reading the whole spec.

Why fastUCP is useful

A merchant publishes a UCP profile at a well-known endpoint describing what it supports:

profile = dict(
    name='DataCenter Parts Co',
    ucp=dict(version='2026-01-11', capabilities=['catalog.search','checkout.create','checkout.complete'], payment_handlers=['mockpay']))

A Python client can then discover and use those capabilities:

class UCPClient:
    def __init__(self, base_url): self.base_url,self.profile = base_url,None
    def discover(self): self.profile = get_json(f'{self.base_url}/.well-known/ucp'); return self.profile
    def has_capability(self, cap): return cap in self.profile['ucp']['capabilities']

The wrapper is small on purpose. It gives the agent a clean boundary: discover merchant capabilities, search a catalog, create a checkout, complete it with an accepted payment handler. The agent reasons at the level of commerce actions instead of raw URLs.

This is one of the places where UCP, MCP, and A2A separate cleanly. MCP is a way to expose tools to models. A2A is a way for agents to delegate to other agents. UCP is the commerce layer: it describes what a merchant, platform, credential provider, or payment provider can do. UCP can ride over REST, MCP, or A2A, but the core idea is still commerce interoperability.

The agent design

I split the demo into three agents.

The prototype used fastllm with a Claude model so I could move quickly, but the model choice is intentionally not the center of the architecture. Each agent is a reasoning step behind a stable interface. In a production version, those calls could be swapped to Nemotron models, especially for teams that need more control over data residency, inference cost, latency, or domain adaptation.

A small business would not need to own a large cluster to try that pattern. They could rent NVIDIA GPU capacity, adapt or fine-tune a Nemotron model on their own procurement examples, and serve it behind the same agent interface. The important part is that the workflow stays the same while the model layer can mature.

That is also where NIM becomes useful. Without an inference layer, teams have to manage model weights, serving backends, dependencies, runtime settings, scaling, and API compatibility themselves. NIM packages optimized inference into deployable microservices, making it easier to switch models, deploy across serving environments, and keep the app code focused on procurement instead of inference plumbing.

1. Requirements Agent

The first agent reads the private bill of materials and engineering policies and translates them into purchasing constraints. It does not call merchant tools or search the web. In a real company the buyer holds proprietary design information, supplier policies, and internal risk thresholds, and not all of that should reach a merchant. Keeping this agent isolated protects that boundary.

It produces a structured brief:

reqs = dict(
    part='high-capacitance MLCC', qty=30000, package='0603', allowed_dielectrics=['X6S','X7R'], min_rated_voltage_v=6.3,
    min_effective_capacitance_uf_at_operating_voltage=20, required_temp=(-40,105), max_ship_days=21,
    require_authorized_distributor=True, require_rohs=True, require_payment_handler=True)
Requirements agent outputThe Requirements Agent turns private engineering context into structured purchasing constraints.

The demo starts with a clean BoM and policy text, but real requirements rarely arrive that way. They live in PDFs, datasheets, approved vendor lists, component databases, spreadsheets, compliance documents, and engineering notes. A production version would need a retrieval layer before the Requirements Agent runs.

An ingestion pipeline could extract text and metadata from those sources, create embeddings, and store them in a vector database such as Milvus. Then the Requirements Agent could retrieve the relevant constraints before deciding whether C147 truly requires 0603, X6S/X7R, RoHS evidence, traceability, and a 21-day ship window.

2. Sourcing Agent

The second agent uses the UCP client to discover the merchant and search the catalog. Its job includes explaining rejections, not only finding matches:

decision = dict(sku='C147-X6S-0603-47UF', status='rejected', reason='ships in 35 days; policy requires shipment within 21 days')

This turned out to be one of the most important lessons of the project. In serious procurement, “no” matters as much as “yes.” A useful agent explains why a part failed: wrong package, insufficient rated voltage, insufficient effective capacitance, unapproved dielectric, missing RoHS evidence, unauthorized distributor, lead time too long, or missing payment handler. Those explanations are what make the system trustworthy.

Sourcing agent outputThe Sourcing Agent searches the merchant catalog and explains accepted and rejected parts.

The mock merchant catalog is tiny, so the Sourcing Agent can qualify parts with simple filtering. Real sourcing is different. A buyer may need to search across millions of SKUs, alternates, datasheets, distributor feeds, lifecycle notices, price breaks, shortage forecasts, and lead-time changes.

That is where CUDA-accelerated retrieval and ranking become relevant: not because this demo needs a GPU to find one capacitor, but because real commerce platforms need to rank many possible parts quickly under changing constraints. This matters most around demand spikes: holiday builds, consumer electronics launches, Prime-Day-type inventory events, or an iPhone-scale production ramp. The MLCC problem is not just one capacitor; it is simultaneous pressure across many high-demand components.

3. Procurement Agent

The third agent handles checkout. It takes an accepted item, creates a checkout session, checks that the merchant accepts the payment handler, and completes the mock transaction:

checkout = ucp.create_checkout([dict(sku='C147-X7R-0603-47UF', qty=30000)])
order = ucp.complete_checkout(checkout['id'], payment_token='tok_mockpay_123')
Procurement agent checkout outputThe Procurement Agent creates checkout and completes the mock order through an accepted payment handler.

What matters here is the payment trust boundary, not the fake token. Agentic commerce cannot mean the model holds a credit card. A safer design separates the merchant, the buyer agent, and the payment credential provider: the merchant advertises accepted handlers, the buyer platform obtains a payment token through one of them, and the merchant validates that token before completing checkout.

Why not one giant agent?

One agent could read the BoM, search products, pick a supplier, and pay. That design hides the reasoning. A staged pipeline is easier to inspect:

constraints = requirements_agent.run(bom, policies)
candidates = sourcing_agent.run(constraints)
order = procurement_agent.run(candidates)

Each agent has a narrower job, private requirements stay isolated, tool access is easier to control, failures are easier to debug, and a human can review before procurement. For a first version, staged orchestration beats a free-form multi-agent group chat.

I did not use NeMo Agent Toolkit in this prototype. The orchestration is intentionally simple: Python calls the Requirements Agent, passes its output to the Sourcing Agent, then passes that result to the Procurement Agent. That made the system easy to inspect while I was learning.

A future version could move this into NeMo Agent Toolkit when the agent boundaries need stronger governance: which agent sees private data, which tools it can call, how agents pass structured outputs to one another, what guardrails apply before checkout, where human approval is required, and how traces and evaluations are collected.

A2A-style handoffs could also matter later, if the sourcing agent needs to negotiate with merchant-side or distributor agents. But the first design principle remains the same: preserve the boundaries between private requirements, external sourcing, and payment.

Engineering tradeoffs

The surprising part of the project was how much of the work was interface design rather than AI. Agents need tools, and tools need clean schemas. If a tool says “send items,” the model may send strings, dicts, or a nested object, so the tool layer needs typed parameters and defensive normalization:

def norm_item(o):
    if isinstance(o, str): return dict(sku=o, qty=1)
    return o

This sounds minor, but it is a big part of building reliable agentic systems. The model is probabilistic and the commerce backend is not, so the boundary between them has to absorb ambiguity.

I also hit a demo architecture issue: a local app calling itself through an HTTP test client creates confusing routing behavior. An in-process merchant adapter was cleaner for the prototype; in production the merchant would be a real external service. The lesson is that demos should preserve the real system boundaries even when the implementation is simplified. The merchant, buyer agent, and payment handler stay conceptually separate.

Scaling beyond one part

The prototype is intentionally small: one synthetic MLCC, one mock merchant, one checkout flow. That is enough to understand the agentic commerce pattern, but it is not the scale at which infrastructure questions become hard.

Dynamo is a later-stage concern. It is not necessary for one MLCC checkout. It becomes interesting when the same system is used by a global commodity manager running many concurrent sourcing jobs across the electrical BoM. If dozens of agents are evaluating MLCCs, inductors, connectors, voltage regulators, supplier risk, lead times, alternates, and shortage scenarios at the same time, inference throughput and latency become product requirements. That is the point where distributed inference serving matters.

What I learned about digital commerce

Agentic commerce turned out to require new infrastructure:

  • a discovery mechanism so agents can understand merchants
  • capability declarations so agents know what actions are supported
  • payment-handler negotiation so agents can transact safely
  • retrieval over messy enterprise data before requirements can be trusted
  • tool schemas strict enough for software but usable by models
  • auditability so humans can understand why an agent made a decision
  • orchestration patterns that keep private reasoning separate from external commerce actions
  • model-serving infrastructure that can evolve from a hosted prototype to customer-controlled deployment
  • scaling infrastructure for many concurrent sourcing and ranking workflows

For MLCC procurement, the agent should behave like a careful technical buyer: preserve the package constraint, avoid unsafe substitutions, respect lead times, check authorized distributor status, verify compliance, explain every rejection, and escalate engineering changes instead of silently making them.

The bigger picture

Tiny components expose the hard problems. An MLCC is cheap compared with a GPU or a production line, but the wrong one can block a build, and a digital commerce system has to understand that. Agentic commerce is powerful where it helps engineers and buyers move through complex sourcing decisions faster, with better explanations and fewer silent mistakes.

A future version of this app would connect more realistic supplier catalogs, add retrieval over engineering and supplier documents, use a production model-serving stack, add evaluation traces, and support human review before checkout. Even the small prototype made the problem clear: the hard part of digital commerce is knowing what should be allowed into the cart in the first place.

Sources