API Tool Engineering Guide
Connect your REST API to a MaiAgent Agent as a tool: request assembly, authentication, timeouts and retries, error responses to the model, and record lookup.
This page is for engineers who want an Agent to call their own systems: how MaiAgent turns the parameters chosen by the Agent into an HTTP request, how to design your API for model use, and what the model sees when a call fails.
For step-by-step instructions in the admin console (where to add a tool and what to enter in each field), see Create an API Tool in the user manual. This page does not repeat those steps. You can also create and manage tools through the REST API, using the same fields described here. See “Tools and Connectors” in the API documentation.
Call Flow
The Agent only decides which tool to call and which parameters to provide. The platform sends the actual HTTP request. Your API does not need to know anything about the model; it only needs to be an HTTP endpoint accessible from the public internet.
Tool Definition Reference
One API tool corresponds to one endpoint and one HTTP method. The platform currently does not import OpenAPI documents. If your API has an OpenAPI specification, create a separate tool for each operation you want to expose to the Agent, then combine the path parameter, query, and requestBody schemas and paste them into “Parameter Schema.”
For field values, format restrictions, and locations in the interface, refer to Create an API Tool: Detailed API Configuration in the user manual. Engineers integrating the API should also know the following:
The tool's
nameis the identifier the model uses to call it. Before it is sent to the model, it is normalized to match^[a-zA-Z][a-zA-Z0-9_]*$, with a maximum of 64 characters. Hyphens become underscores; names that exceed the limit are truncated and given a hash suffix. Usesnake_casefrom the start, such asget_order_status.The model decides when to call a tool based only on its description. If
prompthas a value, it is used; otherwise,descriptionis used. Clearly describe what the tool does, when to use it, and what it returns.Field names when creating a tool through the REST API: API URL is
apiUrl, HTTP method ishttpMethod(get,post,put,patch,delete), headers arerawHeaders, Query parameters arerawQueryParams, parameter schema israwParametersSchema, and display name isdisplayName.
Parameter Schema (JSON Schema)
The platform converts the parameter schema into the model's function-calling schema, then validates the parameters returned by the model against it.
Rules and limitations:
The top level must be
type: "object". Supported features includeproperties,required,default,enum, nestedobject, andarray.Parameter names may contain only English letters, digits, underscores, dots, hyphens, and Chinese characters, and must be 1–64 characters long. Invalid names are rejected when the tool is saved.
The platform supplies
defaultvalues: if the model does not provide a parameter, the platform fills in itsdefaultbefore sending the request. To always send a fixed value without leaving it to the model, usedefaultor enter it directly in Query parameters.Write a
descriptionfor every parameter. The quality of the parameters supplied by the model depends almost entirely on this text. A format example (“in a format such as A123456”) is much more effective than specifying only the type.The parameter name
timeoutis reserved: if the model provides it, the platform uses it as the timeout in seconds for this request and does not send it to your API. Do not use this name for a business parameter.The model's function calling is responsible for honoring
requiredand types. When saving a tool, the platform only checks that the parameter schema itself is valid JSON Schema. Before sending a request, it only checks that all path parameters are present. The model may still occasionally omit required parameters. Have your API return400and explain which field is missing; the model can then fill in the parameters again and call the tool (see How Responses Reach the Model).Parameter schema changes take effect immediately: the tool definition is read when processing begins for each message. The next message after saving uses the new schema, including in an ongoing conversation; you do not need to attach the tool again. For MCP tools, however, the “Allowed Tools” list is a snapshot retrieved when the tool is saved. Retrieve it again after adding tools on the server. See Create an MCP Tool in the user manual.
Do not declare an API key as a parameter and supply it through default. The model can see the parameter schema, so the key would enter the model's context. Put keys in headers or Query parameters instead; see the next section.
Request Assembly
Each parameter in the parameter schema can specify a location (the JSON Schema property's location: path, query, body, or header). The platform places the value supplied by the model in that part of the request. If no location is specified, the HTTP method determines where it goes:
GET
Placed in the query string
Sent only when parameters are explicitly assigned to body
POST, PUT, PATCH
Placed in the JSON body (Content-Type: application/json)
Always sends a JSON object
DELETE
Not sent; specify a location to pass a value
Sent only when parameters are explicitly assigned to body
Key points:
Path parameters: use single braces
{parameter_name}in the API URL, such ashttps://api.example.com/orders/{order_id}, and set the parameter location topath. Values are URL-encoded before substitution. If any path parameter value is missing for a call, the platform does not send the request and reports an error directly. For rules and interface instructions, see Path Parameters and Parameter Locations in the user manual.Configured Query parameters take precedence over model parameters with the same name: if a configured “Query parameter” has the same name as a model parameter, the configured value is used. Put keys that must be sent in the query string in Query parameters so the model cannot override them.
Configured headers take precedence over parameters with the same name: parameters with location
headerare sent as headers using their parameter names. If the tool's “Headers” or contact credentials already contain a header with the same name (case-insensitive), the configured value is used.The body is always a JSON object. form-data, file uploads, and XML are not supported. If your API requires these formats, provide a JSON interface on your side.
{{variables}} in Headers and Query Parameters
Header and Query parameter values can reference conversation context variables ({{contact_id}}, {{source_id}}, {{conversation_id}}, etc.) and parameters declared in the parameter schema using {{parameter_name}}. The platform substitutes them on each call. For available variables and substitution rules, see Substituted {{…}} Variables in the user manual.
{{source_id}} is the variable ISVs use most often. It is the contact's external ID—the sourceId you provide when embedding Web Chat or synchronizing contacts. Your system recognizes its own user IDs. Put this ID in a header (for example, X-User-Id: {{source_id}}) or the query string so your API can query data as that user, without asking the model to “guess” who the user is through the parameter schema.
Authentication
Three methods can be used together, in order of precedence from lowest to highest:
Fixed tool-level credentials: enter
Authorization: Bearer ...orX-API-Key: ...in headers, or enter a key in Query parameters. Calls to your API represent the “entire organization.” After saving, values are masked with****in the admin console. Query parameter values in tool execution records and API request records are also masked.Context variables: as described above, use
{{source_id}}and similar variables to tell your API “who is asking,” and handle authorization on your side. Credentials remain at the tool level.Contact-level credentials (API Credential): bind a set of headers to a specific contact. On a call, they override tool-level headers with the same names. This suits cases where each end user has their own token (your system needs to make calls as the user, rather than as an integration account).
Your backend writes contact-level credentials after the user logs in:
Sending credentials again for the same contact and tool updates the existing credentials; call the endpoint again when the token expires. Credentials apply only in “that contact's conversations.” Other contacts calling the same tool still use tool-level credentials.
Where to Put Keys and Who Can See Them
The platform has no “secret variable” mechanism. Custom names such as {{SECRET_XXX}} are not substituted and are rejected when saving a tool. Enter keys directly in the tool's headers or Query parameters, or write them to contact-level credentials. The only substitutable {{variables}} are the context variables and parameter names listed in the previous section.
Tool editing screen
After saving, header and Query parameter values show only their first and last 4 characters, with **** in between. Values of 8 characters or fewer are displayed entirely as ****
Model context
Header and Query parameter values are not provided to the model. The model sees only the tool name, description, and parameter schema
requestHeaders in tool execution records
Values are displayed as *** for headers whose names match the platform's sensitive header list, and for all headers from contact-level credentials. Name matching is case-insensitive
Request URL and response in tool execution records
Values configured in the tool's “Query parameters” do not appear in the request URL. If a response or error message echoes these values, they are also replaced with ***
The platform's sensitive header list is Authorization, Proxy-Authorization, Cookie, Set-Cookie, X-API-Key, Api-Key, X-Auth-Token, and X-Access-Token. Custom headers with other names (such as X-Partner-Secret) appear in plain text in tool execution records. Therefore:
If you can choose the header name, put keys in a header from the list above.
If you must use a custom header name (such as
x-functions-key), setsensitiveHeaderson the tool through the REST API: an array of header names, with at most 50 entries, each up to 256 characters long. Matching is case-insensitive. Only API tools accept this field, and it is not available in the admin console's tool settings. Once configured, masking also applies when viewing existing execution records. When reading a tool, the read-onlyglobalSensitiveHeadersfield returns the platform's current sensitive header list.Organization administrators cannot modify the platform list. On-premises deployments can replace the entire list using the
TOOL_API_SENSITIVE_HEADERSenvironment variable.Do not put keys in the API URL. The URL (including the query string after
?) appears unchanged in tool execution records.
For the corresponding explanation in the interface, see Who Can See These Values in the user manual.
Passing Conversation Attachments to Tools
API tools can access files uploaded by users in conversations by passing URLs. The platform does not put file contents in the request. Instead, the model fills a parameter you declare with the attachment's download URL, and your API downloads it.
How it works:
After a user uploads files, the model sees each attachment's
id,filename, andfile(download URL). Image attachments also include a filename and URL.Declare a string parameter in the parameter schema to receive the URL. When calling the tool, the model fills it with the corresponding attachment's URL.
Your API downloads the URL with
GET.
Key points:
URL format:
fileis a stable platform URL (https://<API domain>/api/media/...) that redirects to a currently valid signed storage URL on each download. Your download code must follow HTTP redirects. Downloading from this URL does not require an API key.The platform corrects URLs rewritten by the model: when copying a URL, the model may occasionally get the host or protocol wrong. If a URL in a parameter value can be matched to an attachment in this conversation, the platform replaces it with the correct URL before sending the request. URLs that do not match any attachment are sent unchanged.
Multiple files in one call: declare the parameter as an array of strings (
"type": "array", "items": {"type": "string"}) and explain indescriptionthat each element is an attachment URL.Requests are still JSON: the body does not support form-data or binary uploads (see Request Assembly), so the platform cannot send “the file itself” to your API.
Size and format: allowed file types and per-file size limits depend on the conversation platform's attachment settings. See API Conventions: Upload Size Limits. Your API should check
Content-Lengthand file type itself.Retention: conversation attachments have a retention period. Files are deleted and URLs stop working after it expires. If you need to keep a file long term, download it to your own storage when the tool is called. For retention rules, see Credits Billing: Conversation Attachment Storage in the user manual.
Parameter types: parameters support
string,number,integer,boolean,enum, nestedobject, andarray(see Parameter Schema). There is no dedicated “file” type; files are always passed as URL strings.
Attachment download URLs can be accessed without authentication. Anyone who knows the URL can download the file. Your API must not write it to publicly visible logs or responses, or pass it to third parties.
Timeouts, Retries, and TLS
Timeout
The default timeout for each HTTP request is 30 seconds (a platform-level setting, configurable on-premises). It is not the total time limit for the entire tool call. Calls that time out are recorded as timeout, and the model receives “API request timed out.”
Retries
Up to 3 retries after the initial request, for a maximum of 4 attempts, with backoff delays of 1, 2, and 4 seconds. Request errors, including timeouts, and 408, 409, 429, 500, 502, 503, and 504 are retried. Other 4xx responses are not retried.
TLS
The certificate chain and hostname are always verified. If the connection fails because your certificate chain uses an older root certificate without a Subject Key Identifier (some local CAs), only MaiAgent can enable this exception in system administration, per tool or per domain. This option is not available in the admin console's tool settings; contact MaiAgent. Self-signed certificates are not supported.
What this means for your API:
Write endpoints must be idempotent. Retries can send the same
POSTtwice. Deduplicate using a business key in the parameters (order number or external ID), or return409so platform retries still refer to the same record.The entire tool call accumulates the time spent on all requests and backoff delays. Repeated timeouts may take more than 120 seconds, so 30 seconds is not the total upper limit on the model's wait. Keep query endpoints within a few seconds. For long-running work, use “create task → return task ID” and provide a separate query tool.
Returning
Retry-Afterwith429has no effect; the platform uses fixed backoff. Estimate rate limits assuming 3 retries.
How Responses Reach the Model
The model sees your raw response body, without structural parsing:
2xx
Raw body (response.text). An empty body becomes the string None.
Non-2xx (still unsuccessful after retries)
A message starting with API request failed, followed by HTTP <status code>: <raw body>.
Timeout
A message starting with API request timed out, followed by an error description.
Connection error, DNS, or TLS failure
A message starting with API request failed, followed by the exception message.
Insufficient organization Credits
The call is not sent, and the model receives an explanation that the balance is insufficient.
If the response exceeds a certain proportion of the model's context window (80% by default), the platform retains the beginning and end, and adds a “truncated” notice at the start. The middle is removed.
API design recommendations:
Return concise JSON. Return only the fields the model needs, rather than an entire ORM object. Limit each list response to a few dozen records; provide pagination parameters so the model can query additional records.
Use readable error messages, rather than error codes alone.
{"error": "order_id A123 does not exist; please check the number"}helps the model correct parameters or explain the issue to the user better than{"code": 40401}.4xx responses provide feedback to the model: for missing or malformed parameters, return
400and identify the field so the model can try supplying parameters again. Do not wrap errors in200responses; the model will summarize them for the user as successful results.If a response echoes the query string (as some frameworks' error pages do), the platform masks the configured Query parameter values before passing the response to the model. Headers stay out of the body only if your API does not print them there.
To let the model tell the user “no data found,” explicitly return
404with an explanation, rather than200with an empty array.Image URLs in responses: when your API returns an image URL, the model includes it in its reply using Markdown image syntax (
). When Web Chat displays it, the user's browser fetches the image directly from that URL. These are two independent requests: platform → your API (with tool headers and credentials), and browser → image URL (without any tool headers). The image URL must therefore be publicly accessible without authentication and remain valid throughout the conversation. When a short-lived signed URL (such as Azure SAS) expires, images in older messages fail to display. See Creating Conversations and Messages: Images in Message Content.
Records and Debugging
Every call writes a tool execution record. Find these in the admin console under “AgentOps → Tool Execution Records,” or query them through the API:
Available filters: tool, tool_type=api, status (success, failure, pending, timeout), chatbot, start_date, end_date, and query (full text). Each record contains:
The input parameters supplied by the model,
inputParameters, and the actualrequestMethod,requestHeaders(sensitive values masked), andrequestBodysent by the platform.The raw response,
outputResult(after truncation), orerrorMessage.Execution time and status, plus the associated message and Agent.
To read this API, members need the AgentOps “Tool Execution Records” permission. Organization owners are exempt from this restriction.
Suggested debugging order:
Check whether
requestHeadersandrequestBodyin the record have the expected structure. A{{variable}}that was not substituted usually indicates a misspelled variable name or a missing parameter with that name in the parameter schema.If
errorMessagestarts withHTTP <code>, your API returned the error. The raw body follows it.If
status=timeoutbut your logs show a response was sent, the response took more than 30 seconds. Check your p95 first.If the model “does not call the tool,” no record is created. In this case, adjust the tool description and parameter
description, rather than the API.
Billing
Each API tool call that is successfully sent incurs one “API Tool Call” Credits charge. Calls are not sent when Credits are insufficient. Retries for failed or timed-out calls are not charged separately. Specific prices depend on the organization's plan; see the Credits explanation in the user manual.
Pre-launch Checklist
Last updated
Was this helpful?