Connect Fulfil to AI Agents: Automate Sales and Inventory Workflows
Give your AI agent Fulfil tools.
The guide
Learn how to connect Fulfil to ai agents using Truto. Step-by-step guide to tool calling, API quirks, and autonomous workflows.
You want to connect Fulfil to an AI agent so your system can autonomously read inventory, sync customer contacts, execute sales order workflows, and trigger bulk updates based on historical context. Here is exactly how to do it using Truto's /tools endpoint and SDK, bypassing the need to build and maintain a custom Fulfil integration from scratch.
Giving a Large Language Model (LLM) read and write access to your Fulfil ERP instance is an engineering headache. You either spend weeks building, hosting, and maintaining a custom connector, or you use a managed infrastructure layer that handles the boilerplate for you. If your team uses ChatGPT, check out our guide on connecting Fulfil to ChatGPT, or if you are building on Anthropic's models, read our guide on connecting Fulfil to Claude. For developers building custom autonomous workflows, you need a programmatic way to fetch these tools and bind them to your agent framework.
This guide breaks down exactly how to fetch AI-ready tools for Fulfil, bind them natively to an LLM using frameworks like LangChain, LangGraph, CrewAI, or the Vercel AI SDK, and execute complex revenue operations workflows. For a deeper look at the architecture behind this approach, refer to our research on architecting AI agents and the SaaS integration bottleneck.
Why a Unified Tool Layer Matters for Agent Safety
Before writing a line of integration code, decide what layer your agent talks to. This choice determines how safe your production system will be.
Direct API tools - one tool per raw Fulfil endpoint - look convenient but they push provider quirks into the LLM's context. The model has to remember exactly how Fulfil's active record implementations work, how to format vlist arrays for singular object creation, and how to execute workflow state transitions instead of just writing to a state field. Every one of those quirks is a hallucination waiting to happen.
A unified tool layer collapses these complexities behind standard schemas. Your agent sees create_a_fulfil_sales_order or fulfil_sales_orders_execute with strictly typed parameters. That gives you four concrete safety wins:
- Smaller attack surface for hallucination. The LLM only ever chooses from a stable list of function names with heavily documented descriptions. It never invents Fulfil query parameters or misinterprets standard REST semantics.
- Deterministic input validation. Every tool has a strict JSON schema. Invalid arguments are rejected before they hit the ERP, so a broken tool call fails fast instead of creating malformed financial records.
- Decoupled execution context. Your agent does not need to know how to handle cursor pagination, authentication token rotation, or HTTP query string encoding. The Truto proxy layer handles that.
- Framework agnosticism. Because the tools are served via a standard JSON
/toolsendpoint, you can bind them to LangChain today and migrate to Vercel AI SDK tomorrow without rewriting your integration layer.
The Engineering Reality of the Fulfil API
Giving an LLM access to external data sounds simple in a prototype. You write a Node.js function that makes a fetch request and wrap it in an @tool decorator. In production against complex ERP systems, this approach collapses.
Fulfil's API introduces several specific integration challenges that break standard REST assumptions. If you hardcode these interactions into your agent, you will spend your sprints writing defensive integration code instead of improving your model's reasoning.
State Transitions via Execution Workflows
Standard REST APIs typically allow you to update an object's state by sending a PATCH or PUT request with a new status field (e.g., {"status": "confirmed"}). Fulfil does not work this way.
Fulfil relies on strict workflow models. You cannot change a sales order's state by writing to the state field. Attempting to do so will result in an API error. Instead, state changes require calling specific model methods using an execute endpoint. Your agent must understand that to confirm an order, it cannot use update_a_fulfil_sales_order_by_id. It must use fulfil_sales_orders_execute and pass method=confirm along with the specific record IDs.
Summary Serialization vs. Full Object Retrieval
When fetching a single record by ID in Fulfil, the API returns a "serialize" representation. This is the server's summary of the record, which often omits deeper nested fields or associations to save bandwidth.
If an AI agent needs specific, deep fields (like line item details or specific metadata), calling the singular GET endpoint is insufficient. The agent must be instructed to use the list endpoint with a specific where filter (e.g., {"id": <id>}) and explicit fields parameters. Teaching an LLM this distinction through prompting alone is highly error-prone. Truto's tool descriptions encode this logic directly into the schema so the agent knows exactly which tool to pick based on its data requirements.
Vlist Arrays for Singular Writes
Fulfil optimizes heavily for bulk operations. When creating records - even a single record - the API expects the payload to be nested inside a params.vlist array. An LLM instructed to "create a contact" will naturally construct a flat JSON object: {"name": "Acme Corp"}. Fulfil will reject this. The payload must be structured as {"params": {"vlist": [{"name": "Acme Corp"}]}}. The Truto tool schemas enforce this structure natively, preventing the LLM from generating malformed creation requests.
High-Leverage Hero Tools for Fulfil
Truto exposes every Fulfil resource as a tool, but for agentic workflows, a subset of high-leverage operations does the heavy lifting. Here are the core tools your agent will use to manipulate sales and inventory data.
list_all_fulfil_sales_orders
This tool retrieves sales orders using Fulfil's powerful find method. It allows the agent to filter with where clauses, pick specific fields, and sort with ordering. Crucially, Truto follows the cursor through every page automatically, ensuring the agent gets a complete dataset without having to manage pagination loops.
"Find all sales orders created in the last 7 days that are currently in a 'processing' state. Return only the order ID, total amount, and customer ID."
fulfil_sales_orders_execute
Because you cannot write to the state field directly, this tool is the engine for moving data through its lifecycle. It calls a workflow or other model method on sales orders. The agent passes the method name (like confirm or process) and an array of target IDs.
"Confirm sales order ID 10459 by executing the 'confirm' workflow method on it."
create_a_fulfil_contact
This tool creates one or more contacts (customers, suppliers, or other parties) in a single call. The schema strictly enforces the params.vlist array structure, ensuring the agent always formats the payload correctly, even when creating a single contact.
"Create a new customer contact for Jane Doe at Acme Corp, including her email address and billing location, and return the new contact ID."
list_all_fulfil_customer_shipments
Logistics agents need visibility into fulfillment. This tool lists customer shipments, allowing the agent to filter by specific orders or tracking statuses. Like the sales order list tool, it supports complex where filters and handles pagination natively.
"Fetch all customer shipments associated with sales order ID 10459 and return the tracking numbers and current shipment status."
fulfil_products_bulk_update
Inventory agents often need to adjust multiple products simultaneously. This tool writes the same values to several products in one call. The agent provides params.ids (the list of product IDs) and params.values (the fields to update).
"Update the active status to 'false' for products with IDs 992, 994, and 1005."
get_single_fulfil_model_schema_by_id
An agent operating autonomously may encounter a model it doesn't fully understand. This tool acts as an introspection endpoint. It describes a model, listing its fields, types, allowed values, and executable methods with their parameters.
"Describe the 'sales_order' model schema so I can see what workflow methods are available and what parameters they require."
To see the full schema definitions and the complete inventory of available Fulfil tools, visit the Fulfil integration page.
Workflows in Action
Providing an LLM with tools is only the first step. The real value unlocks when the agent chains these tools together to execute multi-step revenue operations.
Scenario 1: Autonomous Order Confirmation and Shipment Tracking
The User Prompt:
"Check for any sales orders from the customer 'TechNova' that are currently in 'draft' state. If you find any, confirm them. Then, check if any of their previously confirmed orders have shipped today and summarize the tracking numbers."
The Agent Workflow:
- The agent calls
list_all_fulfil_contactswith awherefilter for the name 'TechNova' to retrieve the customer ID. - It calls
list_all_fulfil_sales_ordersfiltering by the retrieved customer ID andstate='draft'. - Extracting the IDs of the draft orders, the agent calls
fulfil_sales_orders_executewithmethod='confirm'and passes the order IDs. - It calls
list_all_fulfil_sales_ordersagain, filtering for the customer ID andstate='processing'orstate='done'. - Using those order IDs, it calls
list_all_fulfil_customer_shipmentsfiltering for shipments created or updated today. - The agent formats a natural language summary of the newly confirmed orders and the tracking numbers for the shipped orders.
The Result: The user receives a concise update confirming that 3 draft orders were transitioned to confirmed, and receives a list of 2 tracking numbers for shipments dispatched that day, entirely without human intervention in the ERP.
Scenario 2: Bulk Product Price Updates and Inventory Audits
The User Prompt:
"Find all products in the 'Summer Clearance' category. Increase their base price by 5%. Then, check the current stock counts for these items and alert me if any have fallen below 10 units."
The Agent Workflow:
- The agent calls
list_all_fulfil_productsfiltering for the specific category to retrieve the list of product IDs and their current base prices. - It calculates the new prices in memory (adding 5%).
- Since prices might vary per item, the agent constructs a loop, calling
update_a_fulfil_product_by_idfor each product to apply the specific new price. (If they were all being set to a single flat price, it would usefulfil_products_bulk_update). - It calls
list_all_fulfil_product_counts(or queries specific inventory models if exposed) passing the product IDs and filtering for stock levels< 10. - The agent synthesizes the results, confirming the price updates and listing the specific products requiring restock.
The Result: The user gets an immediate, executed pricing update across a specific product line, paired with a proactive inventory alert, turning a multi-click ERP chore into a single sentence command.
Building Multi-Step Workflows
To execute the scenarios above, you need to bind Truto's tools to your LLM framework. Truto's /tools API returns native JSON schemas that map perfectly to function-calling formats expected by OpenAI, Anthropic, and open-source models.
We provide a dedicated SDK for LangChain (truto-langchainjs-toolset), but this exact pattern works with the Vercel AI SDK, CrewAI, or LangGraph. The proxy layer handles the authentication and HTTP semantics; your code just handles the agent loop.
1. Fetching and Binding Tools
First, you initialize the Truto Tool Manager with your Integrated Account ID. This ID represents the specific authenticated Fulfil instance you are interacting with.
import { TrutoToolManager } from "truto-langchainjs-toolset";
import { ChatOpenAI } from "@langchain/openai";
// Initialize the LLM
const llm = new ChatOpenAI({
modelName: "gpt-4o",
temperature: 0,
});
// Initialize Truto Tool Manager for a specific connected Fulfil account
const trutoManager = new TrutoToolManager({
trutoApiKey: process.env.TRUTO_API_KEY,
integratedAccountId: "fulfil-acct-xyz789",
});
// Fetch the tools directly from Truto's proxy layer
const tools = await trutoManager.getTools();
// Bind the tools to the LLM
const llmWithTools = llm.bindTools(tools);2. Executing the Agent Loop
Once the tools are bound, you drop the LLM into an agent execution loop. Frameworks like LangGraph excel at this by managing the state of the conversation and the intermediate tool calls.
sequenceDiagram
participant App as Application Logic
participant LLM as LLM (GPT-4)
participant Truto as Truto API Proxy
participant Fulfil as Fulfil ERP
App->>LLM: "Confirm draft orders for Acme Corp"
LLM-->>App: ToolCall(list_all_fulfil_sales_orders)
App->>Truto: POST /proxy/fulfil/sales_orders
Truto->>Fulfil: GET /api/v2/model/sales.order
Fulfil-->>Truto: Raw JSON + Pagination Cursors
Truto-->>App: Normalized JSON array
App->>LLM: Submit Tool Result
LLM-->>App: ToolCall(fulfil_sales_orders_execute)
App->>Truto: POST /proxy/fulfil/sales_orders/execute
Truto->>Fulfil: PUT /api/v2/model/sales.order/execute
Fulfil-->>Truto: Execution Status
Truto-->>App: Success Response
App->>LLM: Submit Tool Result
LLM-->>App: Natural Language SummaryWhen the LLM decides to call fulfil_sales_orders_execute, it outputs a structured JSON payload matching the schema Truto provided. The agent framework parses this payload, invokes the local function (which is just a wrapper around a fetch request to Truto's proxy API), and returns the execution result to the LLM's context window.
Because Truto abstracts the pagination and authentication, your application code remains purely focused on orchestrating the LLM's reasoning steps.
Handling Rate Limits in Production
When you give an autonomous agent access to a bulk data API, it will inevitably hit rate limits. Agentic loops can generate hundreds of requests per minute if unconstrained.
It is a critical engineering fact: Truto does not retry, throttle, or apply backoff on rate limit errors. Truto is a transparent proxy layer. When the upstream Fulfil API returns an HTTP 429 Too Many Requests, Truto immediately passes that 429 error directly back to the caller.
However, Truto normalizes the chaotic upstream rate limit information into standardized HTTP headers per the IETF specification. Regardless of how Fulfil formats its rate limit data, your application will receive:
ratelimit-limit: The maximum number of requests allowed in the current window.ratelimit-remaining: The number of requests left in the current window.ratelimit-reset: The time at which the rate limit window resets.
Your application code must read these headers and instruct the agent or the HTTP client to pause. Here is how you handle it safely using an interceptor pattern before the tool returns the error to the LLM:
import axios from 'axios';
// Example interceptor applied to the HTTP client calling Truto
axios.interceptors.response.use(
(response) => response,
async (error) => {
if (error.response && error.response.status === 429) {
const resetTime = error.response.headers['ratelimit-reset'];
const retryAfter = resetTime
? new Date(resetTime).getTime() - Date.now()
: 5000; // Fallback to 5 seconds
console.warn(`Rate limited by upstream API. Backing off for ${retryAfter}ms`);
// Pause execution
await new Promise(resolve => setTimeout(resolve, retryAfter));
// Caller is responsible for initiating the retry
return axios.request(error.config);
}
return Promise.reject(error);
}
);By handling the backoff at the HTTP client level, the LLM is unaware of the delay. It simply waits longer for the tool to return, rather than receiving an error string, panicking, and attempting to hallucinate a workaround.
Wrap-Up
Connecting AI agents to an ERP like Fulfil requires strict architectural discipline. If you expose raw, point-to-point APIs to your models, you will spend your engineering cycles managing HTTP semantics, fighting hallucinations over data structures, and debugging state transition failures.
Using a unified tool layer via Truto’s /tools endpoint isolates the LLM from the underlying complexity of the Fulfil API. The model receives clean, heavily validated JSON schemas that force it to interact with the ERP safely and deterministically. By utilizing tools like fulfil_sales_orders_execute and respecting strict vlist requirements, your agents can execute complex, multi-step revenue operations autonomously.
Stop building fragile custom connectors and start scaling your agentic workflows today.