Connect Acumatica to AI Agents: Sync Data, Files, and Process Actions
Give your AI agent Acumatica tools.
Give AI agents safe, structured access to Acumatica. Learn how to bypass contract-based API quirks, fetch standard tools via Truto's /tools endpoint, bind them to frameworks like LangChain, and orchestrate complex ERP workflows.
In this guide
- 01Connect an Acumatica Instance
- 02Fetch Acumatica Tools via the API
- 03Bind Tools to Your Agent Framework
- 04Execute Workflows and Handle State
The guide
Learn how to safely connect Acumatica to AI agents. Fetch contract-based tools via Truto, bind them to any LLM framework, and automate complex ERP workflows.
You want to connect Acumatica to an AI agent so your system can autonomously sync ERP data, process files, and execute complex business actions. Here is exactly how to do it using Truto's /tools endpoint and SDK, bypassing the need to build and maintain a custom Acumatica integration from scratch.
Enterprise Resource Planning (ERP) systems are unforgiving environments. If you give a Large Language Model (LLM) read and write access to your Acumatica instance, it cannot afford to hallucinate API payloads, guess at contract versions, or misunderstand asynchronous action polling. If your team uses ChatGPT, check out our guide on connecting Acumatica to ChatGPT, or if you are building on Anthropic's models, read our guide on connecting Acumatica to Claude. For developers building custom autonomous workflows, you need a programmatic way to fetch these tools and bind them directly to your agent framework.
This guide breaks down exactly how to fetch AI-ready tools for Acumatica, bind them natively to an LLM using frameworks like LangChain, LangGraph, CrewAI, or the Vercel AI SDK, and execute reliable financial and inventory workflows. For a broader look at this design pattern across enterprise SaaS, read our research on Architecting AI Agents: LangGraph, LangChain, and the SaaS Integration Bottleneck.
The Engineering Reality of the Acumatica API
Giving an LLM access to external ERP data sounds simple in a prototype. You write a basic fetch function and wrap it in a @tool decorator. In production against Acumatica, this approach collapses under the weight of the platform's specific architectural requirements.
If you hardcode these interactions into your agent, you will spend all your development cycles writing defensive integration code instead of improving your model's reasoning capabilities. Acumatica presents several genuinely unique API challenges that break standard REST assumptions.
The Contract-Based REST Paradigm
Acumatica does not use a flat, static REST architecture. It utilizes a "Contract-Based REST API." This means every endpoint is tied to a specific contract endpoint name and a version number (for example, Default/22.200.001).
Standard LLMs are trained to expect simple REST paths like /api/v1/customers. If you let an agent invent the Acumatica URL structure, it will inevitably guess incorrect versions or misspell the endpoint name, resulting in immediate 400 Bad Request or 404 Not Found errors. Truto's tools standardize this by exposing endpoint_name and endpoint_version as strict schema parameters, preventing the LLM from going off-script.
The Nested Payload Trap and PUT for Creation
Standard APIs usually expect flat JSON objects and use the POST method for creating new records. Acumatica requires a deeply nested structure for its fields. When updating or creating a record, Acumatica often expects fields to be wrapped in a { "value": ... } object.
Furthermore, Acumatica relies on the PUT HTTP method for record creation, not just updates. If an LLM attempts to send a standard POST with a flat JSON object like {"CustomerID": "123", "Name": "Acme"}, the API will reject it. Your tool layer must enforce the correct HTTP verbs and JSON formatting.
Asynchronous Action Polling
Acumatica handles business logic through "Actions" - operations like releasing a sales order, confirming a shipment, or calculating taxes. When an agent invokes an action via the API, Acumatica rarely processes it synchronously.
Instead, it returns a 202 Accepted status code along with a Location header. The system is telling the client, "I have queued this action; check back later to see if it finished." An AI agent executing a multi-step workflow must understand that receiving a 202 does not mean the action succeeded. It means the agent must now poll that Location URL until a final success or failure state is reached.
Acumatica Hero Tools for AI Agents
To safely bridge the gap between your LLM's reasoning and Acumatica's strict data model, Truto exposes Acumatica resources as standardized tools via the /tools endpoint.
Here are the highest-leverage operations your agents will use when automating Acumatica workflows.
list_all_acumatica_records
This tool allows the agent to list records of any Acumatica entity (e.g., Customers, SalesOrders, StockItems). It supports OData shaping parameters like $filter, $select, and $expand. This is critical for agents trying to find specific records without pulling down the entire ERP database.
Usage Note: The agent must provide the endpoint_name, endpoint_version, and the entity name. When filtering, the LLM must adhere to standard OData syntax.
"Fetch all open SalesOrders created in the last 7 days from the Default 22.200.001 endpoint, and expand the Details array so I can see the line items."
get_single_acumatica_record_by_id
Retrieves a complete single record by its system ID. This returns the record with its id, rowNumber, note, custom, and all entity-specific fields.
Usage Note: Agents use this after listing records to drill down into the full metadata of a specific transaction or entity before making updates.
"Retrieve the full record for the Customer with ID a1b2c3d4-e5f6-7890-abcd-1234567890ab from the Default 22.200.001 endpoint."
create_a_acumatica_entity_record
Creates a new record for an Acumatica entity by sending its JSON representation to the entity's collection path. Truto handles the underlying PUT requirement.
Usage Note: The agent must ensure it sends the payload structured according to Acumatica's contract fields, including necessary nested objects if required by the specific endpoint version.
"Create a new StockItem record in the Default 22.200.001 endpoint. Set the InventoryID to 'WIDGET-001', the ItemClass to 'CONSUMABLE', and wrap the values according to the schema."
acumatica_actions_execute_action
Invokes a business logic action on a top-level entity in Acumatica. The request body carries the JSON representation of the entity and any parameters the action requires.
Usage Note: This tool returns a 202 Accepted response with a Location header. The agent framework must be designed to handle this async pattern and poll for completion before moving to the next step.
"Execute the 'Release' action on the SalesOrder entity for the order we just created. Provide the entity details in the request body."
create_a_acumatica_attachment
Attaches a file to an Acumatica record by uploading its binary content. This is essential for agents that need to store vendor compliance documents, signed contracts, or generated reports directly on the ERP record.
Usage Note: The agent must address the specific view, field, and record_id where the file should be attached, along with the filename and binary content.
"Attach this parsed vendor invoice PDF to the PurchaseReceipt record ID 98765-abcd. Map it to the Document view and the related attachment field."
list_all_acumatica_attachments
Lists the metadata for all files attached to a specific Acumatica record, returning details like id, filename, href, and comment.
Usage Note: Useful for auditing workflows where an agent needs to verify that required compliance documentation is present before advancing a record to the next status.
"Check the attachments on SalesOrder 10455. List all files and verify if the 'Signed_SLA.pdf' document is present."
For the complete inventory of Acumatica tools, including delete operations, specific file retrieval, and report downloading, review the detailed schema on the Acumatica integration page.
Workflows in Action
When you combine these tools within an autonomous loop, AI agents can execute multi-step revenue operations that previously required manual data entry.
Scenario 1: Automating Vendor Invoice Reconciliation
Accounts Payable teams often waste hours manually matching incoming PDFs to purchase receipts and updating the ERP.
"I received this vendor invoice PDF for PO-9921. Find the corresponding Purchase Receipt in Acumatica, attach the PDF to the record, and execute the 'Release' action to finalize the receipt."
list_all_acumatica_records: The agent queries thePurchaseReceiptentity using an OData$filterto find the record linked to PO-9921.create_a_acumatica_attachment: The agent uploads the vendor PDF, linking it precisely to theviewandrecord_iddiscovered in step one.acumatica_actions_execute_action: The agent triggers theReleaseaction on the Purchase Receipt entity, changing its status from Balanced to Released.
The user gets a fully reconciled ERP record with the audit trail securely attached, without touching the Acumatica UI.
Scenario 2: Autonomous Inventory Auditing
Supply chain managers need real-time checks on stock levels combined with historical context to prevent stockouts.
"Check our current inventory levels for the 'Premium Widgets' category. If any item has fewer than 50 units on hand, create a new note on the item record flagging it for review, and list the attached compliance files for those items."
list_all_acumatica_records: The agent queries theStockItementity, filtering by the specific item class and an available quantity of less than 50.update_a_acumatica_record_by_id: For each low-stock item found, the agent updates the record, appending a high-priority warning to thenotefield.list_all_acumatica_attachments: The agent queries the attachments for those specific items to ensure safety data sheets or compliance files are present before the supply chain team reorders.
The user receives a concise summary of all low-stock items that have been flagged in the ERP, along with a verification of their compliance documentation.
Building Multi-Step Workflows
To execute these workflows, you need a robust agent execution loop. Truto handles the complex proxying, authentication, and endpoint normalization, but your application code must handle the orchestration.
Here is how the architecture flows when an agent executes a multi-step Acumatica workflow:
sequenceDiagram
participant Agent as AI Agent Framework
participant Truto as Truto Proxy Layer
participant Acumatica as Acumatica ERP
Agent->>Truto: GET /integrated-account/<id>/tools
Truto-->>Agent: Returns JSON tool schemas
Agent->>Agent: LLM reasoning & planning
Agent->>Truto: Execute: list_all_acumatica_records
Truto->>Acumatica: GET /entity/Default/22.200.001/SalesOrder?$filter=...
Acumatica-->>Truto: JSON List Response
Truto-->>Agent: Normalized JSON data
Agent->>Agent: Parse data &```
### Handling Rate Limits in the Agent Loop
Before implementing the code, you must understand how Acumatica rate limits work in an autonomous context.
**Factual note on rate limits:** Truto does *not* retry, throttle, or apply backoff on rate limit errors. When the upstream Acumatica API returns an HTTP 429 (Too Many Requests), Truto passes that error directly to the caller. Truto normalizes the upstream rate limit info into standardized headers (`ratelimit-limit`, `ratelimit-remaining`, `ratelimit-reset`) per the IETF spec.
The caller (your agent framework) is solely responsible for implementing retry and exponential backoff logic. If your agent is scraping 500 stock items, you must catch the 429, read the `ratelimit-reset` header, pause execution, and try again.
### Framework-Agnostic Implementation
Whether you use LangChain, CrewAI, or Vercel AI SDK, the pattern remains identical. You fetch the tools from Truto, bind them to the model, and handle the execution in a loop.
Here is a conceptual example using a standard SDK wrapper (like `TrutoToolManager`) and LangChain's `.bindTools()` method to build a resilient execution loop:
```typescript
import { ChatOpenAI } from "@langchain/openai";
import { TrutoToolManager } from "truto-langchainjs-toolset";
import { HumanMessage } from "@langchain/core/messages";
async function runAcumaticaAgent(accountId: string, prompt: string) {
// 1. Initialize the LLM
const model = new ChatOpenAI({
modelName: "gpt-4o",
temperature: 0
});
// 2. Fetch the Acumatica tools from Truto for this specific connected account
const toolManager = new TrutoToolManager({
apiKey: process.env.TRUTO_API_KEY,
accountId: accountId
});
// Generate LangChain compatible tools from the Truto schemas
const tools = await toolManager.getTools();
// 3. Bind the tools to the LLM
const modelWithTools = model.bindTools(tools);
// 4. Start the execution loop
let messages = [new HumanMessage(prompt)];
while (true) {
// Invoke the model with the current context
const response = await modelWithTools.invoke(messages);
messages.push(response);
// If the model decides it doesn't need to call any more tools, break the loop
if (!response.tool_calls || response.tool_calls.length === 0) {
console.log("Agent Final Answer:", response.content);
break;
}
// 5. Execute the requested tools and handle errors (e.g., 429 Rate Limits)
for (const toolCall of response.tool_calls) {
try {
// Find the matching tool implementation
const tool = tools.find(t => t.name === toolCall.name);
console.log(`Executing ${toolCall.name}...`);
// Execute the tool (this routes the request through Truto)
const result = await tool.invoke(toolCall.args);
// Append the result back to the context
messages.push({
role: "tool",
tool_call_id: toolCall.id,
name: toolCall.name,
content: JSON.stringify(result)
});
} catch (error) {
// CRITICAL: Handle HTTP 429 Rate Limits passed through by Truto
if (error.response && error.response.status === 429) {
const resetTime = error.response.headers.get('ratelimit-reset');
console.warn(`Rate limit hit. Must wait until ${resetTime} before retrying.`);
// Inform the agent that it hit a rate limit, allowing it to plan a retry
messages.push({
role: "tool",
tool_call_id: toolCall.id,
name: toolCall.name,
content: JSON.stringify({
error: "Rate limit exceeded",
retry_after: resetTime
})
});
} else {
// Handle standard errors (400 Bad Request, 404 Not Found, etc.)
messages.push({
role: "tool",
tool_call_id: toolCall.id,
name: toolCall.name,
content: JSON.stringify({ error: error.message })
});
}
}
}
}
}
// Execute the workflow
runAcumaticaAgent(
"acu_account_889900",
"Find the inventory receipt for PO-9921 and execute the release action."
);Moving Beyond Brittle Integrations
Giving AI agents access to Acumatica requires precision. The contract-based REST architecture, nested data payloads, and asynchronous actions make direct integration a brittle and error-prone process.
By leveraging Truto's /tools endpoint, you strip away the authentication boilerplate and architectural edge cases, providing your LLM with standard, stable JSON schemas. This drastically reduces hallucination and ensures your agent executes ERP workflows exactly as intended.
FAQ
- How do AI agents handle Acumatica's contract-based REST API versions?
- Truto provides standardized tool definitions that require the agent to specify the endpoint_name and endpoint_version, or maps them behind a unified proxy layer. This prevents the LLM from hallucinating API versions and ensures requests reach the correct ERP contract.
- Does Truto automatically retry Acumatica API rate limit errors?
- No. Truto does not retry, throttle, or apply backoff on rate limit errors. When Acumatica returns an HTTP 429, Truto passes that error to the caller and normalizes the rate limit info into standardized IETF headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset). The caller's agent framework is responsible for implementing retry and backoff logic.
- Can an AI agent attach files directly to an Acumatica record?
- Yes. By using tools like create_a_acumatica_attachment, agents can upload binary content and map it to specific Acumatica data views, fields, and record IDs, fully automating the document attachment process.
- What framework do I need to use Truto's Acumatica tools?
- Truto's tools are framework-agnostic. The /tools endpoint returns standard JSON schemas that can be bound using .bindTools() in LangChain, LangGraph, CrewAI, Vercel AI SDK, or custom execution loops.