Skip to main content
A Custom activity script can call ABBYY Phoenix Plus, the LLM endpoint ABBYY supplies and operates, without writing any HTTP, authentication, or provider-specific code. The activity runs as a step in a Process skill, so the model can read the current transaction and its result can be used by later steps.
ABBYY Phoenix Plus is available on ABBYY Vantage Cloud and requires a contracted entitlement. To enable it for your tenant, contact your ABBYY account team. For an overview, see LLMs in ABBYY Vantage.

Before you begin

  • The Phoenix Plus entitlement is enabled for your tenant, and the ABBYY Phoenix Model connection appears under ADMIN → Configuration → Connections.
  • You have a Process skill with a Custom activity. For the steps, see Custom activity.
  • On the activity’s Available Files tab, select the export formats your script needs. Most scripts need OcrJson. To send page images, you also need a JPEG export, which must be produced before the activity runs.

Create a chat session

Call Context.CreateLlmChatSession() with no arguments to open a session against your tenant’s ABBYY-managed connection. Passing a connection name opens a session against one of your own tenant connections instead.
The rest of this page describes the managed connection. A session opened against your own connection behaves the same way, but bills through your provider and is not subject to the entitlement. The model behind the session is selected and maintained by ABBYY. The session refuses any attempt to change it, so there is no way to request a specific model or version through the managed connection.

Session properties

LastUsage and TotalUsage are objects carrying PromptTokens, CompletionTokens, and TotalTokens.

Reset a session

Reset() clears the conversation history and any pending attachments, so the next message starts fresh. Settings such as SystemPrompt and Temperature are kept, and so is accumulated usage.

Attach content to a message

Attach the transaction data you want the model to see, then send. Attachments queue against the next user message rather than being sent immediately. You can also build conversation history without sending anything, which is useful for few-shot priming:
AttachFile, AttachBinary, and a generic Attach do not exist. Use the methods above.

Attach page images in page order

JPEG exports are ordered by Properties["PageIndex"], so attaching them in the order they appear keeps attachment order aligned with the page numbers the model reports.

Send the message and read the response

SendJson returns an object. If it returns a string, the model did not produce parseable JSON, and the prompt needs tightening rather than the call retrying.

Check how the response finished

Read LastFinishReason before trusting a response. A value of "length" means the response was cut off at the token limit. That is not an error and nothing else signals it, so a script that ignores it will parse a partial result as though it were complete. The fix is to raise MaxTokens or reduce the field set.

Validate the shape before writing values

A response can arrive complete and still be structurally wrong: the right scalar fields but none of the repeating content a skill defines. Check that the reply carries the tables and repeating fields you asked for, and re-ask if it does not, rather than writing the reply into the document unchecked. Reset the session between attempts, and set SystemPrompt again afterwards.

What the managed connection requires

Document context. The managed connection is refused for an execution that has no document pages. This keeps the shared platform credential from being used as a general-purpose LLM gateway. A Custom activity running over a transaction that contains documents satisfies this; a script that opens a session outside that context does not. Metering. Calls through the managed connection are metered against your ABBYY entitlement. Calls through a connection you configured yourself bill through your own provider instead. Consider the volume before pointing a bulk reprocessing job at the managed connection.

Message limits

Both limits are enforced, and a message that exceeds either is refused outright. Size the message in the script before sending rather than letting the call fail. The prompt ceiling is not a single fixed number. It is configured per environment and scales with the number of pages being processed, up to a maximum. On ABBYY Vantage Cloud today, each page allows 500,000 characters, counted over at most three pages, to a ceiling of 1,500,000: Because the ceiling is environment-configured and can change, treat these figures as informational rather than as a contract. Size the message at runtime and degrade when it does not fit, rather than assuming a fixed budget. Exceeding it produces a message of the form:

Errors that retrying cannot fix

A send error mentioning exceeds the maximum allowed size, maximum number of attachments, context length, or too large is terminal. The message is too big or carries too much, and the same call will fail again. The remedies are to lower the JPEG export resolution, send fewer pages, or drop the images and run on the OCR JSON alone.

Errors your script cannot catch

Most failures are catchable in the script with try/catch: connection problems, a failed request, a reply that is not valid JSON, and a prompt that exceeds the size limit. Handle those and carry on. Exceeding the request cap is different. There is a limit on how many LLM calls one script execution may make, scaled by the transaction’s page count. Exceeding it stops the script with a constraint error that a try/catch cannot swallow, in the same way the existing HTTP request cap behaves. This matters if you retry. A validation-and-re-ask loop consumes a call each time it runs, and a loop with no upper bound of its own will eventually hit a limit it cannot handle. Bound your retries.

Sending page images

Page images work, within a practical ceiling set by the prompt budget. Two measured examples, against the ceilings above:
  • A single 1584x1000 page image costs roughly 311,776 base64 characters and about 2,015 prompt tokens. On a one-page transaction that fits inside the 500,000 character allowance, leaving room for the OCR JSON and the prompt.
  • A two-page A4 form scanned at 300 dpi produces roughly 1,326,136 characters of image. A two-page transaction allows 1,000,000, so it is refused. Sending it as images would need each page at about a quarter of its 300 dpi size.
The arithmetic changes with the page count and with any change to the environment ceiling, which is why the message has to be measured before it is sent rather than assumed to fit. Design for the budget rather than against it:
  • Send the OCR JSON as the primary payload, and add page images only for what the text layer cannot carry, such as stamps, signatures, and photographs.
  • Measure the message before sending. If the images do not fit, drop them and rebuild the prompt to match, so the document still processes on the OCR JSON alone.
  • Hold back room for the OCR JSON while sizing images, so a large image cannot crowd out the payload your coordinates are copied from.
  • Reduce image resolution before export where the model only needs to see layout or a stamp rather than fine detail.

Locations and bounding boxes

Do not ask the model for coordinates. The model behind the managed connection cannot ground a bounding box on a page image, and a response that looks like coordinates will not be a measurement.
Asked to return coordinates from a page image, the model returns values on a ten-unit lattice: every number a multiple of ten, uniform heights, and two different fields sharing an identical rectangle. That is a composed layout rather than a measured one, and no coordinate convention setting corrects it. Take geometry from the Vantage OCR layer instead. The OCR JSON export carries measured positions for both text and non-text content, including layout.pages[].pictures[] and barcodes[], so a photograph, logo, or barcode can be located just as reliably as a word. A robust script:
  • Copies coordinates, never estimates them. Every rectangle comes from a position value in the OCR JSON, validated against the OCR page size and scaled to the Vantage page image when the two differ.
  • Enforces provenance. Each region the model returns is measured against the OCR geometry before it is accepted. A region that cannot be traced back to the OCR layer is refused, while the extracted value itself is kept.
  • Requires page attribution. On a multi-page document, a region that arrives without a page number is refused rather than defaulted to page 1.
Use the model for what it is good at, which is reading and classifying. Let ABBYY OCR supply the geometry.

Set MaxTokens deliberately

Leaving MaxTokens at the provider default risks silent truncation on dense documents, visible only through LastFinishReason. Set it explicitly so the cap is yours and legible. For scale, extracting a nine-column table cell by cell across three pages measures roughly 28,000 completion tokens.

Allow enough time

Latency scales with the output tokens generated, not with the size of the input. Phoenix Plus generates roughly 100 completion tokens per second, so a response of 28,000 tokens needs several minutes. Timeout is set in minutes and is capped at the script execution timeout. A two-minute timeout on a document needing 28,000 output tokens will fail at about 121 seconds, having generated only a fraction of the response.

Reduce the OCR payload before sending

A raw OCR JSON export is dominated by the character layer, typically 97 to 98 per cent of its size. Pruning it leaves the text and word positions the model actually needs, at a fraction of the prompt budget. In one measured case a 43,437 character export pruned to 4,842 characters with word positions retained. In another, a 317,296 character export pruned to 32,712 characters. When estimating cost, OCR JSON runs at roughly 2 characters per token. JSON punctuation tokenises badly, so ratios derived from prose do not apply.

Known limitations

To attach a page as an image, use AttachPageImage(page). Passing Page.Image to AttachImage throws Value cannot be null. (Parameter 'fileLink'), on split and unsplit documents alike, because AttachImage expects an exported file rather than a page’s image property. A JPEG export from Document.Exports works with AttachImage.

Example

This script sends pruned OCR JSON and asks for structured field values, taking all geometry from the OCR layer.