The services that can build this cat feeder aren't agent native enough; the one that's agent native enough can't build this cat feeder.
"Agent native" is not "has an API," nor "has MCP." It comes down to two things: for the steps that must be performed by a human (payment, legal declaration, quality sign-off), are they written as states in the protocol; and for every other step, can a caller with no human interface walk through on its own. I used this ruler to measure a dozen manufacturing services along a real order chain, and only Slant 3D's public MCP reached the highest level. Of the two domestic services, one has matching capabilities but its APIs cover only half the order; the other has complete APIs but sells the wrong things.
high reasoning level passed KiCad DRC 5/5. Everything that got stuck involved a counterparty, money, or liability.POST charges it.The agent-native one doesn't do circuit boards or SMT, and for enclosures only offers FDM shipped from the US. Physical goods haven't arrived, so this article evaluates the ordering chain, not delivery.
This piece is written before the goods arrive. As of the night of October 19, a 66×60mm cat feeder control board has been paid for at JLC, the order with SMT is still waiting for me to confirm component polarity; the enclosure has never been printed, the firmware has never been flashed, and the cat has not eaten a single kibble. So what follows evaluates not "a cat feeder built by an agent," but the order chain along its path: how far the agent can walk on its own, and which steps require a human to press the button.
The task was defined as follows: have an agent team build an automatic feeder for a cat—enclosure, circuit board, firmware, app all included—with a human confirming only at the spending gates. The team's three agent tracks (circuit, enclosure, firmware + app) run on Z.ai's open-source ZCode, using GLM-5.3. The board that was ordered is rev A, from my own pipeline: a script generates the spec into a KiCad board, auto-routes, passes DRC; the ZCode team rebuilt it from the same reference spec in round one, and produced rev B (adding motor current sensing) in round two—rev B wasn't ordered because LCSC part numbers hadn't been verified. Design and files are in the public repo fxp/cat-feeder (the repo stores only design and files, not payment or production records). Progress on the software side was good; §02 has the numbers. What actually consumed time was the segment that turns design into money and into shipping labels.
I measured that segment. The ruler was written down before I started; §01 explains.
Everyone uses the term "agent native"; first I'll explain how this piece uses it.
Consider a few existing formulations. Netlify's Mathias Biilmann proposed AX (Agent Experience), broken into three actions: can the agent discover what the service does, can it reliably invoke it, and can it recover from errors. Anthropic's engineering blog discusses how to write tools for agents: make a small number of workflow-oriented tools rather than wrapping CRUD, and error messages should tell the agent what to do next. The MCP specification's tools section states that execution errors should use isError to provide feedback that lets the model self-correct, while "there should always be a human in the loop who can reject the call." These three sources describe the same class of thing: machine-readable contracts, errors that point the way, explicit human nodes. None provides a certification checklist, and Netlify's framing is still the vendor's perspective.
My own ruler is more homespun. Before starting, I had written a fulfillment interface in the proposal—vendors would need to implement six verbs: capability query, validation, quote, order (with payment proof), tracking, cancel. That was for writing adapters; I didn't expect it to become a ruler. Later, as orders went out one by one, I added two clauses learned from the orders: entry point (how to get keys, is there a test environment, do the terms allow machine use) and where is the human (payment, legal declaration, quality sign-off).
Thus the working definition for this article:
A service is agent native when every state transition can be completed by a caller with no human interface, following a public, machine-readable contract; and the transitions that must be performed by a human—payment, legal commitment, quality sign-off—are written as states in the protocol (a pending order, a checkout link), not hidden inside some checkbox in a UI.
This is stricter than "has an API," and stricter than "can be driven by browser automation." Unfolded into a five-rung ladder:
| Level | What it looks like | Example in this article |
|---|---|---|
| L0 | Only a website, no machine entry point | — |
| L1 | Website can be driven by a browser agent: it works, but every step is guessing at the UI | JLC's SMT ordering |
| L2 | Has an API, but keys require approval or offline issuance, or the lifecycle is missing a piece (file ingestion, validation, cancel) | JLC Open Platform, Zaohaowu, PCBWay, etc. |
| L3 | Self-service key acquisition, machine-readable contract, complete lifecycle from quote to cancel | Slant 3D's REST API |
| L4 | Entry point purpose-built for agents: typed tools, read-only/destructive annotations, structured validation output, pending-approval objects | Slant 3D's public MCP |
This is my classification, not an industry standard. The L4 row was written to reflect the best practices I've read, so Slant ranking first is somewhat circular; whether it's truly "best" depends on the item-by-item facts in Table 2, not just the level. The six verbs plus two supplements are the columns in every table that follows.
First the control group, because every "stuck" later must be read against it.
The team is three real agent tracks (circuit, enclosure, firmware + app), running on ZCode, conversing via a team bus and a versioned shared contract. Numbers from two real runs:
| Round one | Round two | |
|---|---|---|
| New bus messages this round | 25 | 21 (cumulative 46) |
| Contract version | to v14 | to v24 (cumulative) |
| Tool calls | 192 | 226 |
| Call failures | 0 | 0 |
| All three tracks simultaneously active | 350 s | 460 s |
Round one wall-clock 1,749 s; round two 2,754 s, input 19.2 M tokens, output 0.26 M. The same PCB task was repeated individually five times: GLM-5.3 at reasoningLevel=high routed successfully 5/5, KiCad DRC 0 errors 0 unconnected; the default max level only 3/5, both failures from reasoning timeout—one hit the 1,500 s limit, the other had the upstream disconnect after 653 s on the first request.
"0 call failures" counts only the calls themselves, not domain errors: across those five runs there were 141 MCP calls, about 10% returning domain errors (invalid spec, DRC failure), all understood and fixed by the model—none were pipeline problems.
Outputs were independently verified after the fact; the agent's own reports were not trusted: kicad-cli pcb drc on the exported board reported 0 errors 0 unconnected; firmware host tests 21 items 517 assertions passed, pio run compiled; app on simulator 33/33. Never flashed, never on a real phone; enclosure fit checks used a box-estimate, of 32 parts 30 had estimated dimensions. All DRC passing doesn't mean the circuit is correct: a local small model reversed an LED on the first try, and DRC reported nothing.
These numbers make one point: when the counterparty is kicad-cli, headless Blender, PlatformIO, or similar local tools, the agent almost never gets stuck. Their common trait: file in, file out, exit code speaks—no accounts, no money, no legal consequences. KiCad's official entry point for automation follows the same pattern: kicad-cli is primarily for reading and exporting; the IPC API in KiCad 9 and 10 can only connect to a running GUI, and only the PCB editor can load plugins. We stayed on the command line throughout; once when I opened the KiCad GUI on a real machine using a button, it was blocked by macOS quarantine attributes instead.
Even the agent's own "brain" has a step only a human can do: on the first spike run, the BigModel account balance was exhausted (error code 1113), and the run could only be completed after I topped up.
So when I say "got stuck" below, I always mean this class: has a counterparty, has money, has liability.
JLC is where real money was spent this time. Three orders, totaling ¥361.99: one v1 board (no MARK points), one v2 board (with MARK points, prepping for SMT), plus an SMT order attached to v2. The v1 was actually a duplicate order: boards without MARK points won't be converted for SMT by the platform—a rule I only discovered after ordering.
I first checked every step against the open platform. API coverage looks like this:
| Order step | Open platform | What was actually done |
|---|---|---|
| Pricing | Endpoint, tested with real account and works | Endpoint |
| File ingestion | Only accepts a public URL for JLC to download; no upload endpoint | Web upload |
| Create PCB order | Endpoint exists (not actually called; every success is a real order) | Web |
| Create SMT order | None; SMT endpoints only cover querying BOM components, orders, progress, and sending parts | Web, seven steps |
| Validation (DFM) | None | Checked during web upload; ~4 hours after payment, human goes to order list to confirm component polarity |
| Payment | When creating order, isAdvancePayment=false, endpoint won't charge prepayment | Human pays on web: top up first, then combined payment |
| Tracking | Endpoint exists (not actually called) | Web order list |
| Cancel | None among 14 PCB endpoints | Web; cancel after payment incurs engineering fee, no changes accepted after production starts |
On the entry-point side there are also a few items, each defensible on its own:
403 Request IP source invalid, and a home network's outbound IP change breaks it—proxies also fail.So the real orders were placed through an agent-driven browser in my logged-in account. This path worked, and also showed me what "L1" feels like:
<div> and <span>, not buttons; popups and onboarding guides swallow clicks; refreshing the page resets the form;What bothered me most were two places where "a machine should have spoken, but no one did."
First, component orientation. In JLC's component library, SOT-23 (3-pin) and SOT-223 at 0° differ from KiCad by 180°—visible only in the SMT preview, not caught by DRC, and not exposed in the API. I found Q1 and U2 reversed in the preview, rotated each 180° in the web editor and saved, then added offsets for these two footprints in the generator. Whether other footprints have the same offset, I haven't verified—every order requires a human eye on the preview.
Second, "can this design be SMT'd?". This is as clear-cut a validation question as they come, and the answer is a rule written on a help page—yet there's no corresponding endpoint. I paid for a duplicate order because of this.
To be fair, JLC doesn't lack agent awareness. Its EDA team has published a whole row of agent-oriented things on GitHub: easyeda-client-cli (the client's built-in CLI, runnable as an MCP server), easyeda-api-skill, a WebSocket gateway extension, and a locally-run "order check" extension for JLC DFM rules. PCB process validation, JLC has done partly, placing it in the EDA client extension rather than the open platform API; whether SMT rules (MARK points, component orientation) are covered, I haven't checked.
JLCPCB's own two AI design blog posts (September 18, October 14) both discuss how to let an agent operate the editor; where they mention ordering, it's about exporting Gerber, BOM, and coordinates, then uploading to JLCPCB for instant quotes after design verification. Neither post mentions an ordering API. They connected the agent to the drawing board, not to the cash register.
The JLC Open Platform itself isn't crude: signatures match the official example byte-for-byte, every response carries J-Trace-ID, and business error codes are clear. It feels designed for a different kind of caller: someone who knows what they want to order and is willing to go to the web for the last few steps. An agent needs the reverse: before knowing the outcome, every step should have a machine-readable answer.
Zaohaowu (I call it Hi3D; two names for the same platform—confirmed only by the counterparty, "Zaohaowu" doesn't appear on hi3d.ai's public pages) is another kind of L2.
A fair disclaimer first: it sells figurines, not manufacturing capability. I'm measuring it because the task needed a high-precision enclosure printing outlet, and it was the only domestic outlet I had with a test environment.
Its strengths are specific. There's a separate test environment (api-test.zaohaowu.com), and the full path works: Basic auth exchanges for a 24-hour token; image-to-image submission goes from PROCESSING to SUCCESS in about 20 seconds; order/create carries requestId for idempotency; order/fulfillment/batch queries fulfillment, order states 0–7 and fulfillment states each have enums; after order/cancel, the order reads "closed" and the fulfillment reads "cancelled." Create, query, cancel—three verbs all worked on the real interface. When errors occur, it also speaks up: a forged image URL is rejected with 1003 Image URL invalid, please upload image first, a non-portrait photo with 5003 Please upload a portrait photo—both with readable reasons.
The gaps are equally specific:
price in order/create is pass-through, not validated; prices come from an offline product catalog from the vendor. An agent can't get a "how much will this cost" number it can bind to.imageUrl must be an image the vendor itself recognizes; object photos and renderings can't go in. It can't accept the cat feeder enclosure.modelId, productId, skuId all are. Test credentials against the production domain return 40001; I still haven't received the production set.1000 System error, not "not found."I wrote a six-item requirements list for this (self-upload model print products, model submission method, quote, production credentials, payment method, size and review limits), which I still haven't sent. Until they respond and I've placed a real order, I won't say "an agent placed an order through Hi3D's API." All I can say is: in the test environment, create, query, and cancel worked.
The two domestic services side by side form an interesting complement: JLC has matching capabilities but incomplete APIs; Zaohaowu has complete APIs but mismatched capabilities.
Slant 3D is an FDM print farm in Boise, Idaho, USA; the FAQ states they print in the US and ship from the US. In my original proposal I noted it as "the only one with self-service key acquisition," wrote an adapter per the OpenAPI spec, but never called it with real keys, and later didn't include it in the chain: it doesn't do circuit boards, and enclosures are US-shipped FDM. Re-reading it this time, I found it had already added a second door.
Door one, REST API. The OpenAPI 3.0.3 spec (~40 operations) says in its description: "This spec is for automated tools and AI Agents." It includes an x-agent-hints block that compresses the order flow into one line: upload file → draft order → process order → fulfillment → webhook. The draft order is described as "price first, then process," the process order as "start production and charge," and cancellation is limited to "not yet started." The docs site also says webhooks carry HMAC-SHA256 signatures, retry every minute on failure, up to ten times. Among manufacturing APIs I've read, this is one of the most complete lifecycles.
Its other side is equally blunt. Keys can only be generated by a human in a web session (POST /apiKey doesn't accept Bearer); once a human binds a card on the account page, POST /orders/{id} charges it in one shot. The spec has no idempotency key and no sandbox. This leaves the gate to the caller: Slant guarantees drafts don't charge; whether to charge is your program's decision.
Door two, public MCP. This is the segment I most want to discuss. https://www.slant3d.com/mcp requires no key, no login. The llms.txt says "AI agents can quote and order real 3D-printed parts in two ways," and the FAQ has a dedicated question: "Can an AI agent order a 3D print?" The answer is Yes.
I had the agent run a read-only plus quote test against it (October 20, no order placed, no address or email filled in):
initialize and tools/list worked normally. 10 tools, each annotated: quote_raw_pricing is read-only; quote_set_quantity is marked as not touching the external world; list_* are marked idempotent.quote_upload_part: upload a self-generated 20mm cube (base64). One call returned: quote_id, bounding box, volume, and per-unit price, subtotal, setup fee, and lead time at 1, 100, and 1000 units (1 unit 3–5 business days, 100 units 5–7, 1000 units 2–3 weeks), plus print_feedback—running nine checks (mesh, flat placement, chamfer, bottom text, wall thickness, thin column, spider-like, support, support area), yielding one severity: warning suggestion to "add 1mm bottom chamfer," and stating "can be ordered as-is." The response includes both text and structuredContent, plus a next_steps line telling the agent which tool to call next.quote_set_quantity: change to 5 units, get back new per-unit price and lead time.quote_id returns isError: true with only "Unknown quote_id."; an 18-byte garbage STL is rejected at the input validation layer, returning a validation array as-is.I didn't call quote_shipping_options (requires name, address, email—I don't want to write personal info into a public service) or quote_checkout (requires email, generates a Stripe checkout link). Per its tool descriptions: shipping is saved onto the quote; after checkout link payment, the order automatically enters the print farm and the customer receives a confirmation email. So shipping and checkout were read from descriptions, not tested.
It got four things right:
quote_id threads upload, quantity change, shipping, and checkout into one line—exactly what the Anthropic article calls "make workflow-oriented tools."quote_checkout returns a payment link for the human to pay. The agent knows when to stop and what to hand off to whom.What it didn't get right: MCP has no tracking or cancel—those two verbs exist only in REST; error messages are too sparse, Unknown quote_id. doesn't tell the agent what to do next; in the same response, part price $1.37 and per-unit price $2.77 coexist with no field-level explanation (I couldn't tell the difference); cancel and refund rules are scattered across spec, docs site, and user agreement with slightly inconsistent wording: spec says cancelable before start, docs site says cancel triggers refund, user agreement says fees non-refundable after start.
And its boundaries: the user agreement is a short 2023 document that doesn't mention API, automation, or AI; materials are PLA, PETG, carbon-fiber PETG, and OPM; printing and shipping are in the US; international shipping I haven't verified.
By this point, two questions have merged into one: at which step does the human appear, and in what form?
On my side, I built a gate: the model has no "place order" tool, only quote and prepare-order card; ordering can only go through an endpoint that requires a backend-signed confirmation token, bound to order intent, quote, vendor, price, file sha256, shipping address, and user; confirmation also requires a fresh WebAuthn (designed as Touch ID; real-device Touch ID not yet verified). This is my design. It requires the other side to hand me something bindable: a quote with an ID, price, and validity period, or a pending-payment order.
What the other side hands over looks like this:
| Service | Pending-approval object | Who approves, how | What public docs say it binds |
|---|---|---|---|
| Slant 3D · MCP | quote_id | Human opens Stripe checkout link and pays | Quote total; whether file hash and address are bound, not stated |
| Slant 3D · REST | DRAFT order | No third party: Process directly charges the card on file | Gate is on the caller |
| JLC | Pending-payment order (SMT order holds inventory for 7 days) | Human pays at web checkout | Not stated |
| PCBWay | Cart order, pending-payment package | Partner account balance or credit, or redirect to payment page for human | Not stated |
| OSH Park | Pending-payment order after checkout | Human pays after receiving email; API doesn't accept credit cards | Not stated |
| Zaohaowu | Order (test environment: order is "paid" on creation) | Docs don't say | price is pass-through, not bound |
| My own gate | Order intent | Human confirms in UI, passes WebAuthn | Quote, file sha256, address, user |
The rightmost column—almost none of the vendors' public materials answer it.
The 2026 payment protocols have already laid the vocabulary. UCP's checkout state includes requires_escalation, at which point the merchant must provide a continue_url and at least one message with severity requires_buyer_input or requires_buyer_review: when to stop and hand the link to the buyer is stated by a status field, not by guessing. ACP's session has pending_approval, plus quote_id, purchase_order_number, and payment terms. Stripe's wallet for agents requires writing the spending reason in human-readable text, waiting for approval in Link, expiring after 30 minutes, retrying with idempotency keys, and offering a test mode that never charges. The MCP spec also says there should always be a human in the loop who can reject the call. Related background in earlier pieces: UCP, Agent Onboarding Gates (identity and payment), Offline Agentic Commerce (physical commerce).
But they all target catalog items: a shopping cart, a final price. In existing flows, I haven't found a "upload file, get price, then approve" custom-part example; ACP's schema has quote_id, UCP allows omitting payment during "generate quote, manage cart"—both left hooks but no examples. Among the manufacturing service docs I've read, none mentions implementing any of these protocols. Among the services I've read, Slant's path from quote_id to checkout link is the only one that's public, keyless, callable right now, and used for custom parts.
Legal declarations are the other half of the same problem. JLC makes it a checkbox in the UI—opening and closing the reading popup auto-checks it, effectively turning "read" into "agreed"; an agent in a loop reads it once and has signed it. Shapeways goes to the opposite extreme: the model upload endpoint has two required boolean fields,; hasRightsToModel and acceptTermsAndConditions, where the caller declares they have rights to the model and accept the terms. Written as fields, a machine can see them—but one line of code makes a commitment on behalf of a human, which is exactly what I want to prohibit. UCP's approach is worth copying: make "requires buyer review" a state; until that state is resolved, the flow doesn't proceed.
One more dimension: the more convenient, often the looser. Lining up payment methods, there are three kinds:
The third kind is most convenient for the agent, and also the loosest for the principal. In physical-world APIs, defaults often speak louder than endpoints: Printful v2 makes orders start as drafts, requiring a separate confirm call to charge; Printify's new-store default is auto-approve orders after 24 hours, entering production without an API call; Mouser's order endpoint has SubmitOrder=false, returning only a summary without submitting. The agent runtime side is the same: in ZCode's spike, -p mode defaults to yolo—on a disposable mock service, an agent confirms an order with one curl line; user-level hooks can be bypassed four ways, and the agent can modify its own hooks; only the OS sandbox blocked all attempts. So the gate must live in a process the agent can't reach—you can't count on the service to place it for you, nor on the runtime to place it for you.
Among catalog-type physical services, some already lay out the full agent path: Shippo's hosted MCP uses OAuth, no key copying; every docs page has an agent instruction block; the docs state that buying a shipping label charges the account, and write operations require confirmation before execution. But a shipping label isn't a custom part—there's no "upload geometry, get price" step.
The two tables below combine what I read and what I tested. ★ marks my own testing or hands-on work; everything else is from public materials read on October 20, 2026; docs visible only after login I didn't access, written as "not seen" or "unknown"—absence of evidence is not evidence of absence.
Table 1 · Entry points and contracts
| Service | Level | How to get keys | Test environment | Contract | Agent entry point |
|---|---|---|---|---|---|
| Slant 3D · MCP ★ | L4 | Public, no key needed | — | Tool schema, with read-only/idempotent/destructive annotations | Is itself |
| Slant 3D · REST | L3 | Self-service registration; keys can only be generated in a web session, 3 per account | Not seen | OpenAPI 3.0.3, self-described "for automated tools and AI Agents" | Spec has x-agent-hints |
| Zaohaowu ★ (test env) | L2 | AK/SK issued offline | Yes, full path walkable | Feishu doc, flow diagrams blank | None |
| JLC Open Platform ★ | L2 | Personal registration; key shown once; outbound IP whitelist | No | PDF doc in console | None; llms.txt points to web form |
| PCBWay | L2 | Email approval, for partners with their own website | Vague (examples call it sandbox) | Auto-generated help page, plus a 2018 PDF | No official (third-party MCP wrapper exists) |
| JLCPCB International / JLC3DP | L2 | Apply + approval, for enterprises and distributors; 3D ordering tier has unpublished monthly order volume threshold | Not seen | No OpenAPI, only Java SDK | No official |
| OSH Park | L2 | Contact support to enable | Not seen | Ruby gem; docs page returns 404 | None |
| Craftcloud | L2 | Couldn't find entry point | Order body has isTestOrder flag | Swagger 2.0, no auth declaration, no upload | None |
| Shapeways | L2 | Self-service, OAuth2, API free | Not seen | Human-readable docs, no OpenAPI | None |
| Xometry | — | Supplier-side API only, apply by email | Not seen | Supplier API has OpenAPI and llms.txt | Docs face agents, but serve suppliers; buyer-side public API not found |
| Protolabs / Hubs / Fictiv | — | No public API found (Fictiv has only cXML Punchout) | — | — | None |
Table 2 · Order lifecycle
| Service | Validation | Quote | File ingestion | Pending-approval state | Who pays | Tracking | Cancel |
|---|---|---|---|---|---|---|---|
| Slant 3D · MCP ★ | Yes: nine checks, tiered, with suggestions | Yes, quote_id, three quantity tiers with lead times | base64 or https URL | quote_id | Human, Stripe link | None | None |
| Slant 3D · REST | Partial: file metrics; human review before production start | Quote endpoint; draft order includes shipping | Pre-signed upload + confirmation | DRAFT to Process | Human binds card first, then call charges | Polling + signed webhook | Yes, before start |
| Zaohaowu ★ | Partial: review flags, error codes with reasons | No, price pass-through | Only accepts vendor-approved images | Docs don't say | Docs don't say | Yes ★ | Yes ★ |
| JLC ★ | No (assembly rules are on the web) | Yes ★ | Public URL, no upload | Pending-payment order | Human, web checkout | Polling (not called) | Not in endpoint list |
| PCBWay | Human review after ordering | Yes, no ID, no validity period | URL or base64 | Cart to pending-payment package | Partner credit, or redirect page for human | Polling | Yes, mainly before payment |
| JLCPCB International / JLC3DP | Partial: Gerber pre-parse; 3D file parse includes "unavailability reason" | Yes, shape undisclosed | Upload | Unknown | Prepaid balance (inferred) | Polling | Not in endpoint list |
| OSH Park | Render preview, approval (for human or vision model) | Yes | Upload or URL | After checkout, wait for email payment | API doesn't accept credit cards, human pays | Polling | Yes, limited to early states |
| Craftcloud | None | Yes, priceId, quoteId, cart has expiresAt | Not in spec | Yes | Redirect checkout (human); invoice Net30 | Polling | Not on customer side |
| Shapeways | Partial: printable field | No quote endpoint; model info has per-material prices | Byte upload, plus two boolean declarations | No, one-call ordering | Card on file, charge on call | Polling | No |
Reading these two tables, a few observations:
For service providers (each with a counterexample from above):
quote_id; Craftcloud has quoteId and cart expiry; Zaohaowu has none)print_feedback; JLC's rules are on help pages and in previews)requires_escalation; counterexamples are JLC's auto-checked checkbox and Shapeways' boolean fields)Unknown quote_id. and 1000 System error both fail this bar)For people building agents:
curl line. The gate is the verifier; verifiers are scarcer than generators—this is the main thread of "R&D in the AI Native Era", and this is another instance.One thing I want to watch for: when will the protocols that write "human" into the spec first produce a custom-part example.
llms.txt and MCP across domains (October 20). Public portion at fxp/cat-feeder; rest in private repos.First published 2026-10-20