Skip to content

Why your OpenAPI document isn't converting to MCP tools, and how to fix it

Find the message the importer gave you, learn what it means, check it against your document and decide what to change. Every message below is real output from Riviera's importer for a small test document with one defect, except the address check at import, which we ran separately.

By Riviera EngineeringPublished Claims checked

In short

  • Read the first cause, fix it, import again. The importer reports one cause per operation, the first it hits. Fixing it can reveal the next, so a document usually takes a few rounds.
  • Three kinds of cause look alike. Something wrong in your document, a step you still have to take in the product, and something Riviera’s importer does not support. Each problem below says which it is, because the right response differs.
  • Do not edit the document to make the message go away. The document is a contract with your API. A change that makes the importer accept it but no longer matches what your API sends, such as removing nullable from a field that can be null, shows up when an agent calls the tool, as an output contract mismatch.
  • A tool in the list is not a tool that works. Analysis reads your document and never calls your API. The last section covers what only a real call can show.

This guide is for fixing one document. For what we measured across thirteen public documents, read what converts cleanly and what doesn’t. For every supported construct and exclusion code, see importing an API.

Reading the import result

After Analyze API, each operation is in one of three states: ready to add, needs a decision first, or can’t become a tool. An operation that can’t becomes a reason in the form CODE: detail. The code is stable, so search for it. The detail names the field or the rule.

A problem in the document itself, such as an unsupported version or invalid syntax, refuses the whole document and nothing is partly imported. Most problems in a single operation do not stop the others.

Every example below is a small document with a single defect. To try one yourself, replace https://api.example.com/v1 with a real public HTTPS address first: Riviera refuses a server that does not resolve on the public internet, and a placeholder host does not (see the server address).

Find your symptom

What you seeCodeUsuallyGo to
The whole document is rejected before any operation is listedVERSION_UNSUPPORTED INVALID_YAML YAML_UNSUPPORTED WEBHOOKS_ONLY DOCUMENT_LIMIT OPERATION_LIMITYour document, or a limitThe whole document is refused
Every operation fails with the same message about the serverSERVER_REQUIRED SERVER_VARIABLES ORIGIN_UNSAFEYour documentThe server address
Operations fail on authentication, or all wait for a choiceSECURITY_ALTERNATIVES SECURITY_COMBINED SECURITY_UNSUPPORTED HEADER_RESERVED SECURITY_SCOPESA limit, or a stepAuthentication
Create and update operations are missing, reads are fineBODY_OPTIONAL MEDIA_UNSUPPORTEDYour document, or a limitRequest bodies
List operations are missing, or an operation says its response isn't describedRESPONSE_ROOT RESPONSE_REQUIRED RESPONSE_VARIANTSYour document, or a limitResponses
A message names a schema field such as nullable or oneOfSCHEMA_UNSUPPORTED SCHEMA_TYPEA limitSchema constructs
A message about a referenceREF_SIBLINGS REF_CYCLE REF_UNSUPPORTED REF_MISSINGYour document, or a limitReferences
Two operations with similar paths both fail, or a cookie is mentionedPATH_AMBIGUOUS PARAMETER_UNSUPPORTEDYour document, or a limitPaths and parameters
Operations are listed but none is selected or added yetno code, a sentenceA stepOperations waiting for a decision
Tools exist, and a call failsHTTP_BACKEND_ERROR HTTP_RESPONSE_INCOMPATIBLEYour API, or the document no longer matches itA generated tool is not a working tool

The whole document is refused

Other refusals of the whole document: INVALID_JSON (a syntax error), DUPLICATE_KEY (the same key twice in one object), INVALID_STRUCTURE (for example info.title or info.version is missing), PATH_REF (a path item written as a $ref), DIALECT_UNSUPPORTED (jsonSchemaDialect is set), OPERATION_LIMIT and ORIGIN_LIMIT (more than ten different API addresses in one source). Operations using HEAD, OPTIONS or TRACE fail as METHOD_UNSUPPORTED and still count toward the 200. A webhooks section with an empty paths object is not an error: it gives zero operations.

The OpenAPI version isn't recognised

Symptom
VERSION_UNSUPPORTED, with no operations listed.
Cause
Riviera reads OpenAPI 3.0.0 to 3.0.4 and 3.1.0 to 3.1.2. A Swagger 2.0 file has a swagger field instead of openapi. In YAML, openapi: 3.0 is read as the number 3, not as a version with three parts.
How to check
Look at the first line of the file. Swagger 2.0 starts with swagger: "2.0". A two-part version such as 3.0 or 3.1 is refused as well.
What to do
Write the full version, such as 3.0.3 or 3.1.0. Convert a Swagger 2.0 file to OpenAPI 3 with a converter you trust and review the result before importing it.
Whose problem
Your document (fixing it is enough), and a Riviera limit (the importer does not support it today).
VERSION_UNSUPPORTED: Use OpenAPI 3.0.0–3.0.4 or 3.1.0–3.1.2 as JSON or YAML.
In YAML, write the version unquoted only if it has three parts, such as 3.0.3.

The document only describes webhooks

Symptom
WEBHOOKS_ONLY.
Cause
Webhooks are requests your API sends. An agent can only call operations under paths. A document with both is fine: the webhooks section is left out and counted in the result.
How to check
Check that the document has a paths object with operations in it.
What to do
Import the document that describes the requests your customers make to you. If it exists only as a webhooks file, there is nothing here for an agent to call.
Whose problem
Your document (fixing it is enough).

YAML that is valid but refused, or a document that is too big

Symptom
INVALID_YAML names a line. YAML_UNSUPPORTED says valid YAML uses something Riviera does not read. DOCUMENT_LIMIT or OPERATION_LIMIT for size.
Cause
Riviera reads one YAML 1.2 document and refuses features whose meaning differs between YAML versions: merge keys, custom tags, directives, numbers written with a leading zero or in hexadecimal or octal, and more than one document in a file. The document has to be 1 MiB or less and have at most 200 operations.
How to check
Search the file for <<: and for --- appearing twice. Check the size of the file and count the operations. A document that is only over the byte limit because of its formatting can be minified. The limits apply after YAML aliases are expanded.
What to do
Write merged keys out in full, remove the extra documents, or split a large document into parts of at most 200 operations each. Keep only the operations an agent should call.
Whose problem
Your document (fixing it is enough), and a Riviera limit (the importer does not support it today).

The server address

Riviera calls your API from its own servers, so each operation needs exactly one absolute address to call, with no credentials, query string or fragment in it (SERVER_UNSAFE) and no traversal or encoded separators in its path (SERVER_PATH). This is the most common cause in the documents we ran, and the cheapest to fix.

No server, a relative server, or more than one

Symptom
Every operation fails with SERVER_REQUIRED.
Cause
OpenAPI lets servers be missing (then the document is relative to wherever it was fetched), be relative like /api/v3, or list several, such as production and sandbox. Riviera has to know which one to call, and it does not guess.
How to check
Look for servers at the top of the document, and for a servers list on a path or an operation, which overrides it. The detail says which case it is.
What to do
Declare one absolute HTTPS server URL, at the top of the document. If you keep a sandbox in the document, import a copy that lists only the server agents should call.
Whose problem
Your document (fixing it is enough), and a Riviera limit (the importer does not support it today).
servers: []                              # or missing
  Importer: SERVER_REQUIRED: Declare exactly one effective absolute server URL.
  Server alternatives require review outside this importer.

servers: [{ url: "/api/v3" }]
  Importer: SERVER_REQUIRED: Use an absolute execution server URL;
  relative servers are unsupported.

servers: [{ url: "https://api.example.com/v1" },
          { url: "https://sandbox.example.com/v1" }]
  Importer: SERVER_REQUIRED: Declare exactly one effective absolute server URL.
  Server alternatives require review outside this importer.

A server variable has no default

Symptom
SERVER_VARIABLES: Server variable region needs a default value.
Cause
A templated server, such as https://{region}.example.com, needs a default for every variable. Riviera calls the default. It will not choose between the values in an enum.
How to check
Open the variables object under the server and check that each name in braces has a default, that the default is one of the enum values if you list them, and that it is a plain host label or path segment.
What to do
Add a default that is the region or environment agents should use. A default can fill a host label or a path segment. It cannot add a port or a second host.
Whose problem
Your document (fixing it is enough).

The server looks right, and the import still refuses it

Symptom
ORIGIN_UNSAFE: Use an HTTPS public execution server. Private targets are blocked in production.
Cause
The import checks the address after reading the document. It must be HTTPS and must resolve to a public address. http://, localhost, a private IP, a host name that resolves only on your private network, and a host name that does not resolve are all refused. A public name behind a firewall passes this check and can still fail when a tool is called. A placeholder such as api.example.com did not resolve when we checked on 13 October 2026, so it falls in the last group.
How to check
Check that the address is https. Look up the host name (for example with dig): every address it returns must be a public one, and the name must resolve at all. A host that resolves only on your private network is refused.
What to do
Use the public HTTPS address of your API. An API that is only reachable internally needs a public entry point before agents can use it through Riviera.
Whose problem
Your document (fixing it is enough), and a Riviera limit (the importer does not support it today).

This check runs when you choose Analyze API in the product. The importer's reading of the document alone does not make it, which is why the fixtures in this guide cannot show it. The checks we ran against the address code, with the production setting, refused http://api.github.com (HTTPS is required), https://localhost, https://10.0.0.5, https://api.example.com and a name under .invalid (the last two because they do not resolve), and accepted https://api.github.com.

Authentication

Riviera supplies the credential, so it has to know exactly which one. Where a document offers a choice, either you choose a method in the product, or the importer cannot.

The document lists more than one way to authenticate

Symptom
SECURITY_ALTERNATIVES on every operation that lists them, or SECURITY_COMBINED when one requirement names two schemes.
Cause
In OpenAPI, security: [{a: []}, {b: []}] means a or b, and security: [{a: [], b: []}] means a and b together. Riviera supports one requirement per operation, so it cannot pick, and it cannot send two credentials.
How to check
Check the top-level security and each operation’s own security. An operation’s overrides the top-level one, so look at both.
What to do
Keep the one method agents should use, in a copy of the document you import. Your API still accepts the others, and the document no longer mentions them. If two schemes must be sent together, the importer cannot express that today.
Whose problem
A Riviera limit (the importer does not support it today), and your document (fixing it is enough).
security:
  - token: []
  - key: []
    Importer: SECURITY_ALTERNATIVES: Multiple security alternatives are unsupported.
    Supply one explicit requirement.

security:
  - token: []
    key: []
    Importer: SECURITY_COMBINED: Combined security schemes are unsupported.
    Supply one supported requirement.

security:
  - token: []                  # one requirement: accepted

Basic authentication, a key in the query string or a cookie

Symptom
SECURITY_UNSUPPORTED: Use HTTP bearer, a header API key or supported OAuth.
Cause
Riviera can supply an HTTP bearer token, an API key sent in a header, OAuth client credentials and per-user OAuth through your own authorization server. OpenID Connect is read as per-user OAuth. HTTP Basic, an API key in a query string or cookie, mutual TLS and any other scheme are not supported.
How to check
Look at the scheme the operation’s requirement points to, under components.securitySchemes: its type and, for an API key, where it is sent (in).
What to do
If your API also accepts the credential as a bearer token or a header, describe that. If it does not, there is nothing the importer can use, and the operation stays excluded.
Whose problem
A Riviera limit (the importer does not support it today).

The credential is declared as a header parameter

Symptom
HEADER_RESERVED: The Authorization header carries credentials or routing, so an agent cannot be asked for it.
Cause
A credential written as an ordinary parameter would be an argument the agent has to supply. Riviera keeps credentials out of the agent's hands, so it refuses header parameters that carry credentials or routing, such as Authorization, Proxy-Authorization and Host. Other credential-bearing headers, such as X-Api-Key, are not caught: they would be accepted as an argument the agent has to supply, so declare those as security schemes too.
How to check
Search the operation’s parameters for in: header entries named Authorization or another reserved header such as Host, Content-Length or Connection. Header parameters named Content-Type, Accept or Cookie fail differently, as CONTRACT_INCOMPATIBLE.
What to do
Remove the parameter and declare the credential as a security scheme, so Riviera supplies it.
Whose problem
Your document (fixing it is enough).

OAuth declared with a flow Riviera does not run

Symptom
SECURITY_SCOPES: Declare one supported flow that grants all operation scopes. The message does not name the flow.
Cause
Of the OAuth flows, Riviera supports client credentials and authorization code. A document that offers only the implicit flow (we ran that case) has no flow it can use, and the message reports it as a scope problem. Password is refused by the same rule.
How to check
Open the scheme under components.securitySchemes and read its flows. Check that the scopes the operation asks for are declared on a flow that is supported.
What to do
Declare authorizationCode for per-user sign-in, or clientCredentials for a service credential, if your authorization server supports it. Supporting per-user sign-in also takes setup on your side: see authentication.
Whose problem
A Riviera limit (the importer does not support it today), and your document (fixing it is enough).

Request bodies

Create and update operations fail, reads don't

Symptom
BODY_OPTIONAL: Only required JSON request bodies on write methods are supported.
Cause
OpenAPI treats a request body as optional unless it says required: true. Many documents leave the flag out for bodies that are in practice required. Riviera only builds a tool from a body that is required, because an optional body would have to be sent or omitted on the agent’s guess. A body on a GET is refused for the same reason.
How to check
Open the failing operation’s requestBody and look for required: true beside content.
What to do
Add required: true if the API rejects a call without a body. If the body really is optional, do not add it: agents would then always be asked for one. That operation stays excluded.
Whose problem
Your document (fixing it is enough), and a Riviera limit (the importer does not support it today).
requestBody:
  content:
    application/json: { schema: { ... } }
  Importer: BODY_OPTIONAL: Only required JSON request bodies on write methods are supported.

requestBody:
  required: true
  content:
    application/json: { schema: { ... } }   # a tool the user must still review

Forms, file uploads and a second body format

Symptom
MEDIA_UNSUPPORTED: Declare only application/json for this body or response.
Cause
Only application/json bodies can become tools. Multipart and form bodies, XML, and binary uploads cannot. A body that lists application/json beside another type is refused as well, because Riviera would have to choose.
How to check
Count the keys under content. There must be exactly one, and it must be application/json.
What to do
Remove the other media types from the copy you import, if your API accepts or returns JSON for the same operation. The same rule applies to a response, and the key must be exactly application/json: application/json; charset=utf-8 is refused. If the operation is a file upload, it cannot be a tool today.
Whose problem
Your document (fixing it is enough), and a Riviera limit (the importer does not support it today).

Responses

An operation that returns a list

Symptom
RESPONSE_ROOT: Use an object-root JSON response; scalar/array output contracts are unsupported.
Cause
A tool's output is a JSON object. A response whose top level is an array or a single value cannot be one.
How to check
Open the success response’s schema. If it begins with type: array, that is the cause.
What to do
Editing the document cannot fix this. The schema has to describe what your API sends, and your API sends an array. The fix is in the API: return an object that wraps the list, such as { items: [...] }, and describe that. Until then the operation stays excluded.
Whose problem
A Riviera limit (the importer does not support it today).

The success response isn't described, or uses a wildcard

Symptom
RESPONSE_REQUIRED, with either Declare JSON response schemas, or an explicit no-content 204 response. or Wildcard success codes are unsupported.
Cause
The tool needs an output schema. A 200 with a description and no content, a response keyed 2XX, or an operation that declares only default and error responses, does not promise any particular result. Several success statuses with different schemas fail as RESPONSE_VARIANTS, because the tool has one output. That includes a 200 with a JSON body next to a 204.
How to check
Open the operation’s responses. Each 2xx entry needs content with an application/json schema and an object at its root, or the code must be 204 with no body.
What to do
Describe the real response in the document. If every success status returns the same object, use one schema. Remove a status only if your API never returns it. If the shapes genuinely differ, such as a 200 with the resource and a 202 with a job id, the operation cannot be a tool today.
Whose problem
Your document (fixing it is enough), and a Riviera limit (the importer does not support it today).

Schema constructs

Riviera compiles each schema into a check that runs when an agent calls the tool, so it accepts only schemas it can check exactly. Nothing that changes what a value may be is dropped silently, except an unknown format, and example, default and deprecated are read and left out.

Nullable fields, unions and composition

Symptom
SCHEMA_UNSUPPORTED: Schema field nullable is unsupported. The same for oneOf and allOf. In OpenAPI 3.1, type: ["string", "null"] gives SCHEMA_TYPE: Declare one explicit non-null JSON type.
Cause
nullable, type arrays, oneOf, anyOf, allOf, not and discriminator are the common ones, and the list is open: the importer refuses any keyword that is not on its supported list, including readOnly and writeOnly (very common on id fields), x-nullable, xml and externalDocs. It reports the first one it meets. A schema with no type at all, such as a field that only has a description, fails as SCHEMA_TYPE too.
How to check
Read the field name in the detail, then find it in the schemas the operation uses: its parameters, its request body and its success response. A schema in an error response or an example does not matter.
What to do
Only simplify a schema where the simpler version is true. Remove nullable if the API never sends null. Give a field an explicit type. A field that really is a union of shapes cannot be described today, and the operation stays excluded. If you remove nullable from a field that can be null, the tool will import and a real response will not match its output schema. For readOnly and writeOnly, removing the keyword from a response property is harmless, and removing it from a request property makes agents supply that field.
Whose problem
A Riviera limit (the importer does not support it today).
note: { type: string, nullable: true }
  Importer: SCHEMA_UNSUPPORTED: Schema field nullable is unsupported.
  Use the documented explicit JSON schema subset.

note: { type: [string, "null"] }          # OpenAPI 3.1
  Importer: SCHEMA_TYPE: Declare one explicit non-null JSON type.
  Nullable, unions and inferred types are unsupported.

payment: { oneOf: [ ... ] }
  Importer: SCHEMA_UNSUPPORTED: Schema field oneOf is unsupported.

meta: { description: "Anything" }          # no type
  Importer: SCHEMA_TYPE: Declare one explicit non-null JSON type.

Some things people expect to fail do not. A format Riviera does not know, such as ulid, is ignored and the operation still converts. So is a vendor extension in a schema, such as x-internal (but not x-nullable, which changes what a value may be), and so is a webhooks section.

References

Fields written beside a $ref

Symptom
REF_SIBLINGS: Reference siblings are unsupported. Put fields in the referenced definition.
Cause
In OpenAPI 3.0 anything written next to a $ref is ignored by the specification, and 3.1 allows some of it. Riviera does not read fields beside a $ref in either version, and refuses the operation instead of dropping them without telling you.
How to check
Search for a $ref line followed by another key in the same object.
What to do
Move the description into the referenced definition, or remove it. Check that you are not dropping a constraint, such as a different maximum, that the sibling field was meant to add.
Whose problem
Your document (fixing it is enough).

Recursive, external and missing references

Symptom
REF_CYCLE for a schema that contains itself, REF_UNSUPPORTED for a reference to another file or URL, and REF_MISSING for a pointer that leads nowhere.
Cause
Riviera follows local references, starting with #/, and only for what a tool uses: parameters, the request body and success responses. A tree that contains itself, such as a folder with child folders, has no finite schema. A reference to another file would need a fetch the importer does not make.
How to check
For REF_MISSING, copy the pointer and look for exactly that path, including capitalisation. For REF_UNSUPPORTED, search for $ref values that do not start with #/.
What to do
Bundle a multi-file document into one before importing. Correct a broken pointer. A recursive schema has to be replaced with one that stops at a fixed depth. That is true to your API only if it never nests deeper, so it is a design decision about the API, not a mechanical edit.
Whose problem
Your document (fixing it is enough), and a Riviera limit (the importer does not support it today).

Paths and parameters

Two paths with the same shape

Symptom
PATH_AMBIGUOUS on both operations.
Cause
/invoices/{id} and /invoices/{number} are the same address with different names. A call could reach either, so Riviera refuses both rather than choose.
How to check
List the paths and compare them with the placeholders replaced by braces.
What to do
Check whether they are one resource with inconsistent placeholder names, such as GET /invoices/{id} and PUT /invoices/{number}. If so, use the same placeholder name in the path and in the parameter's name, and merge the two path items, so no operation is lost. This only works when they use different methods: two GETs on one resource cannot be merged. If they really are two different lookups, give them different fixed segments in your API.
Whose problem
Your document (fixing it is enough).

A cookie, or a parameter with a complex value

Symptom
PARAMETER_UNSUPPORTED: Use named path/query/header parameters; cookie parameters are unsupported. Other PARAMETER_* codes cover object values and serialization styles.
Cause
Tools take path, query and header parameters with simple values, and query arrays sent as repeated fields. Cookie parameters, object-valued parameters and other serialization styles are not supported.
How to check
Check each parameter’s in, its schema’s type and its style.
What to do
If your API also accepts the value in a header or the query, describe that. Otherwise the operation stays excluded.
Whose problem
A Riviera limit (the importer does not support it today).

CONTRACT_INCOMPATIBLE is the importer’s catch-all for an operation it cannot map and has no more specific reason for: “Repair the path/mapping. Match each path placeholder, declare required scalar arguments, and remove credential/routing headers or unsupported serialization.” Check that every {placeholder} in the path has a path parameter of the same name, that each is marked required, and that no header parameter is on the reserved list above.

Operations waiting for a decision

An operation can be convertible and still not ready. These show a sentence, not a code, and they are steps in the product, not defects.

What the importer saysWhyWhat to do
Review the write operation and its effects before enabling.POST, PUT, PATCH and DELETE change data. Reads are selected for you, writes never are.Select the write operations you want agents to use, on purpose.
This operation is deprecated in its source. Review before enabling.The document marks it deprecated.Decide whether an agent should still use it.
Choose static/service or per-user authentication, or the intended OAuth flow, before creating a Draft.A bearer scheme can be a shared service token or a per-user credential. The document does not say which.Choose the method when you add the operation.
Provide a matching project-scoped credential reference before creating a Draft.An API key or a client-credentials scheme needs a credential for the exact server.Save the credential for this API, then add the operation.
Delegated per-user OAuth is required. Configure the customer authorization server for this exact backend resource and scopes in Settings before enabling or publishing.Per-user sign-in needs your authorization server set up for this API.Follow authentication.

In the research behind our other guide, 121 of the 124 operations that converted were waiting on one of these decisions, and the other 3 needed none. None was a tool in a draft yet. That is expected, not a failure.

Size and count limits

LimitValueCodeWhat to do
Document size1 MiBDOCUMENT_LIMITMinify if it is only formatting, or split the document.
Operations in one document200OPERATION_LIMITSplit into documents of at most 200 operations, keeping the ones agents need.
Nesting and nodes40 levels deep, 50,000 nodesDOCUMENT_LIMITFlatten or split.
Schema size5,000 values in one schema of a tool, 40,000 in distinct schemas for one importSCHEMA_TOO_LARGE IMPORT_BUDGETRemove fields an agent does not need, or split the document.
Reference expansion2 MiB of text or 250,000 values across the documentREF_LIMITShare fewer or smaller definitions.
API sources in a project10SOURCE_LIMITReimport an existing source.

We tested two of these. A document of exactly 200 operations is accepted and 201 is refused whole with OPERATION_LIMIT. A document padded with whitespace past 1 MiB is refused with DOCUMENT_LIMIT, and the same document without the padding is accepted. The other values are the importer’s documented limits.

A generated tool is not a working tool

Everything above is about whether a tool is generated. Analysis reads your document and never calls your API, so it cannot know whether the tool works. Agents read what you publish, not the draft, so a call is the first real test.

SituationWhat Riviera doesWhat to check
Your API answers with an error statusThe agent is told the call failed with the HTTP status (HTTP_BACKEND_ERROR). The error body is not passed on.Activity shows the tool, the outcome and the status. Read your API's own logs for the reason.
Your API answers 2xx, but not with JSONThe call is reported as HTTP_RESPONSE_INCOMPATIBLE. The request succeeded on your side.Check the content type your API returns. Verify what the call changed before retrying a write.
Your API answers 2xx with JSON that doesn't match the output schemaThe agent still receives the response and the call counts as a success, but Activity shows the diagnostic category “output contract”.Compare a real response with the schema. This is where a removed nullable shows up.
Your API redirectsThe redirect is not followed (HTTP_REDIRECT_REFUSED).Describe the final address in the document, not the one that redirects. Check what happened to a write.
Your API is slow or largeA call that does not finish in 60 seconds is reported as a timeout, and the tool may still have run on your side: verify before retrying a write. A response over 5 MiB fails as an upstream error.Check your API's response time and size for the arguments the agent sent.
The agent sends arguments that don't match the input schemaRiviera stops before calling your API and says so.Activity shows that nothing ran on your side.

To see a real call, publish a version, connect a client as described in connecting an AI client and open Activity. A model test is a different check: it asks which tool a model would choose and does not call your API. Nothing here says whether an agent will choose the tool or fill it in well. That needs its own test with the requests your customers make.

A repeatable way to work through it

  1. Fix anything that refuses the whole document first. Those errors hide every operation.
  2. Declare one absolute public HTTPS server. It clears the largest group of failures at once.
  3. Group the remaining operations by code. A few codes usually account for most of them.
  4. For each code, decide whether it is a defect in the document, a step to take, or a limit. Fix the first kind, take the second, and leave the third excluded rather than distort the document.
  5. Import the corrected document again. Riviera lists what was added, changed and removed, and your edits to tools are kept.
  6. Add the operations you want, resolve each decision, edit the names and descriptions agents will read, and publish.
  7. Make a real call and read it in Activity.

What this guide doesn’t cover

  • The examples are small documents with one defect each. A real document has several, and only the first is shown for each operation, so expect more than one round.
  • The messages are those of Riviera’s importer as of 13 October 2026. Another converter will refuse different things and say different words. Messages change as the importer does, and the codes are the stable part.
  • We checked the importer’s analysis and address checks. We did not check any provider’s API, call a model or measure how often each cause occurs. For counts across real documents see the study, which is small and was chosen.
  • The call-time behaviour in the table comes from reading the code that executes a call. We did not run a live call to produce each row.