All Products
Search
Document Center

Object Storage Service:Intelligent document continuation

Last Updated:Mar 20, 2026

Intelligent document continuation is an AI-driven feature that generates coherent, contextually consistent follow-up content based on your existing text, subject, and style.

Prerequisites

Before you begin, ensure that you have:

  • An IMM Project mapped to your OSS bucket. Intelligent Media Management (IMM) is the AI model orchestration layer that processes continuation requests. This is a one-time setup. If you haven't completed it, follow Get started or AttachOSSBucket before calling this API

  • The required permissions. For details, see Permissions

Usage notes

  • Intelligent document continuation supports synchronous processing only.

  • Requests must use the POST method.

  • Anonymous access is denied.

Warning

The content parameter accepts up to 19,500 bytes of URL-safe Base64-encoded text. Requests that exceed this limit return an error.

How it works

Submit a POST request to an object in your bucket with x-oss-process=doc/continue. The file name is a placeholder only — OSS reads the content parameter, not the file content, to run the continuation.

The response contains the generated text in Output.Text. Check Output.FinishReason to determine whether the task has completed:

ValueMeaningAction
nullThe task is still running. In SSE mode, more events follow.Continue reading events.
stopThe task completed successfully.Read the final Output.Text value and stop.

Parameters

Operation: doc/continue

Request parameters

ParameterTypeRequiredDescription
contentstringYesThe source text, URL-safe Base64-encoded. Maximum 19,500 bytes.
formatstringNoResponse format. json (default) returns a single packet with the complete response. event-stream enables Server-Sent Events (SSE) mode and returns multiple incremental packets.
historystringNoPrevious continuation outputs for multi-turn sessions, URL-safe Base64-encoded. See Multi-turn continuation.

Response parameters

ParameterTypeDescription
RequestIdstringThe unique request identifier.
Output.TextstringThe generated continuation text.
Output.FinishReasonstringTask status: null (running) or stop (completed).

Use the RESTful API

JSON mode

JSON mode returns a single response packet containing the complete generated text.

Sample request

POST /example.doc?x-oss-process HTTP/1.1
Host: doc-demo.oss-cn-hangzhou.aliyuncs.com
Date: Fri, 28 Oct 2022 06:40:10 GMT
Authorization: OSS4-HMAC-SHA256 Credential=LTAI********************/20250417/cn-hangzhou/oss/aliyun_v4_request,Signature=a7c3554c729d71929e0b84489addee6b2e8d5cb48595adfc51868c299c0c218e

x-oss-process=doc/continue,content_RXJuZXN0IEhlbWluZ3dheSdzICJUaGUgT2xkIE1hbiBhbmQgdGhlIFNlYSIgaXMgYSB0YWxlIG9mIGFuIG9sZCBmaXNoZXJtYW4sIFNhbnRpYWdvLCBhbmQgaGlzIGVwaWMgc3RydWdnbGUgdG8gY2F0Y2ggYSBnaWFudCBtYXJsaW4uIFRoaXMgc3RvcnkgaXMgYSBwcm9mb3VuZCBleHBsb3JhdGlvbiBvZiBodW1hbiBlbmR1cmFuY2UsIHBlcnNldmVyYW5jZSwgYW5kIHRoZSBiYXR0bGUgYWdhaW5zdCB0aGUgZm9yY2VzIG9mIG5hdHVyZS4gU2FudGlhZ28ncyB1bndhdmVyaW5nIGRldGVybWluYXRpb24gYW5kIGRpZ25pdHkgaW4gdGhlIGZhY2Ugb2YgYWR2ZXJzaXR5IHNlcnZlIGFzIGEgdGVzdGFtZW50IHRvIHRoZSBzdHJlbmd0aCBvZiB0aGUgaHVtYW4gc3Bpcml0Lg==

Sample response

{
  "RequestId": "6761445E8A0E5D383974169B",
  "Output": {
    "Text": "Ernest Hemingway's \"The Old Man and the Sea\" ...\n\nSet in the Gulf Stream off the coast of Cuba...",
    "FinishReason": "stop"
  }
}

SSE mode

SSE mode streams the response as incremental events. Each event contains the cumulative text generated so far — not just the new fragment. Read FinishReason to detect when the stream ends.

Sample request

POST /example.doc?x-oss-process HTTP/1.1
Host: doc-demo.oss-cn-hangzhou.aliyuncs.com
Date: Fri, 28 Oct 2022 06:40:10 GMT
Authorization: OSS4-HMAC-SHA256 Credential=LTAI********************/20250417/cn-hangzhou/oss/aliyun_v4_request,Signature=a7c3554c729d71929e0b84489addee6b2e8d5cb48595adfc51868c299c0c218e

x-oss-process=doc/continue,format_event-stream,content_RXJuZXN0IEhlbWluZ3dheSdzICJUaGUgT2xkIE1hbiBhbmQgdGhlIFNlYSIgaXMgYSB0YWxlIG9mIGFuIG9sZCBmaXNoZXJtYW4sIFNhbnRpYWdvLCBhbmQgaGlzIGVwaWMgc3RydWdnbGUgdG8gY2F0Y2ggYSBnaWFudCBtYXJsaW4uIFRoaXMgc3RvcnkgaXMgYSBwcm9mb3VuZCBleHBsb3JhdGlvbiBvZiBodW1hbiBlbmR1cmFuY2UsIHBlcnNldmVyYW5jZSwgYW5kIHRoZSBiYXR0bGUgYWdhaW5zdCB0aGUgZm9yY2VzIG9mIG5hdHVyZS4gU2FudGlhZ28ncyB1bndhdmVyaW5nIGRldGVybWluYXRpb24gYW5kIGRpZ25pdHkgaW4gdGhlIGZhY2Ugb2YgYWR2ZXJzaXR5IHNlcnZlIGFzIGEgdGVzdGFtZW50IHRvIHRoZSBzdHJlbmd0aCBvZiB0aGUgaHVtYW4gc3Bpcml0Lg==

Sample response (abridged — full stream contains many events; only first and last shown)

HTTP/1.1 200 OK
Content-Type: text/event-stream;charset=UTF-8
Transfer-Encoding: chunked

id: 0
event: Result
data: {"RequestId":"67614545E3FA66313474AAC8","Output":{"Text":"Er","FinishReason":"null"}}

id: 1
event: Result
data: {"RequestId":"67614545E3FA66313474AAC8","Output":{"Text":"Ernest","FinishReason":"null"}}

...

id: 131
event: Result
data: {"RequestId":"67614545E3FA66313474AAC8","Output":{"Text":"Ernest Hemingway's \"The Old Man and the Sea\" ... making his triumphs and tribulations deeply personal. Through Santiago's eyes, we see ...","FinishReason":"stop"}}
Each event's Text field contains the full accumulated output, not just the new fragment. To display only the new text, compare consecutive events and extract the difference. Stop reading when FinishReason is stop.

Consuming the SSE stream

The following pseudocode shows how to process events and detect completion:

previousText = ""

for each SSE event received:
    parse event.data as JSON
    currentText = data.Output.Text
    newFragment  = currentText[len(previousText):]  // extract only the new portion
    display(newFragment)
    previousText = currentText

    if data.Output.FinishReason == "stop":
        break  // stream is complete

Multi-turn continuation

Pass previous continuation outputs in the history parameter to build on earlier results. Encode the array as URL-safe Base64 before submitting.

History array format

[
  {"content": "text generated in the first turn"},
  {"content": "text generated in the second turn"}
]

Example: two-turn continuation

Turn 1 — Submit the initial request with content only:

x-oss-process=doc/continue,content_<base64url_initial_content>

Turn 1 response:

{
  "RequestId": "...",
  "Output": {
    "Text": "Santiago gazed out at the horizon, the weight of eighty-four fishless days pressing on his shoulders...",
    "FinishReason": "stop"
  }
}

Turn 2 — Wrap the Turn 1 output in the history array, Base64-encode the array, and submit with both content (new source text) and history (encoded array):

History array before encoding:

[
  {"content": "Santiago gazed out at the horizon, the weight of eighty-four fishless days pressing on his shoulders..."}
]

Turn 2 request:

x-oss-process=doc/continue,content_<base64url_new_content>,history_<base64url_encoded_history_array>

Each subsequent turn appends the latest Output.Text to the history array before encoding.

Use SDKs

The following SDK examples all use the same pattern: encode your source text as URL-safe Base64, then pass it as the content value in the x-oss-process instruction.

Java

OSS SDK for Java 3.17.4 or later is required.

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.common.utils.IOUtils;
import com.aliyun.oss.model.GenericResult;
import com.aliyun.oss.model.ProcessObjectRequest;

import java.io.IOException;
import java.util.Formatter;

public class Demo {
    public static void main(String[] args) throws ClientException, com.aliyuncs.exceptions.ClientException {
        // Specify the endpoint of the region where the bucket is located.
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // Specify the Alibaba Cloud region ID. Example: cn-hangzhou.
        String region = "cn-hangzhou";
        // Obtain access credentials from environment variables.
        // Set OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET before running this code.
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // Specify the bucket name. Example: examplebucket.
        String bucketName = "examplebucket";
        // The object name is a placeholder — its content is not read.
        String key = "example.docx";
        // Specify the source text.
        String content = "Ernest Hemingway's \"The Old Man and the Sea\" is a tale of an old fisherman...";
        // URL-safe Base64-encode the source text.
        String encodeContent = BinaryUtil.toBase64String(content.getBytes())
                .replaceAll("\\+", "-")
                .replaceAll("/", "_")
                .replaceAll("=", "");

        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();

        try {
            StringBuilder sbStyle = new StringBuilder();
            Formatter styleFormatter = new Formatter(sbStyle);
            // Build the processing instruction.
            styleFormatter.format("doc/continue,content_%s", encodeContent);

            ProcessObjectRequest request = new ProcessObjectRequest(bucketName, key, sbStyle.toString());
            GenericResult processResult = ossClient.processObject(request);
            String json = IOUtils.readStreamAsString(processResult.getResponse().getContent(), "UTF-8");
            processResult.getResponse().getContent().close();
            System.out.println(json);
        } catch (OSSException oe) {
            System.out.println("Error Message: " + oe.getErrorMessage());
            System.out.println("Error Code: " + oe.getErrorCode());
            System.out.println("Request ID: " + oe.getRequestId());
        } catch (ClientException ce) {
            System.out.println("Error Message: " + ce.getMessage());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}

PHP

OSS SDK for PHP 2.7.0 or later is required.

<?php
// Obtain access credentials from environment variables.
// Set OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET before running this code.
$ak = getenv('OSS_ACCESS_KEY_ID');
$sk = getenv('OSS_ACCESS_KEY_SECRET');
// Specify the bucket name. Example: examplebucket.
$bucket = 'examplebucket';
// The object name is a placeholder — its content is not read.
$objectKey = 'example.docx';
// Specify the source text.
$txt = "Ernest Hemingway's \"The Old Man and the Sea\" is a tale of an old fisherman...";

// URL-safe Base64-encode the source text.
$base64url = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($txt));
// Build the processing instruction.
$body = sprintf("x-oss-process=doc/continue,content_%s", $base64url);

$httpVerb = 'POST';
$contentMd5 = base64_encode(md5($body, true));
$contentType = '';
$date = gmdate('D, d M Y H:i:s T');
$stringToSign = $httpVerb . "\n" . $contentMd5 . "\n" . $contentType . "\n" . $date . "\n" . "/{$bucket}/{$objectKey}?x-oss-process";
$signature = base64_encode(hash_hmac('sha1', $stringToSign, $sk, true));

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://{$bucket}.oss-cn-hangzhou.aliyuncs.com/{$objectKey}?x-oss-process");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Date: ' . $date,
    'Authorization: OSS ' . $ak . ':' . $signature,
    'Content-Type: ' . $contentType,
    'Content-Md5: ' . $contentMd5,
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

$response = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($response === false) {
    echo "Error: " . curl_error($ch);
} elseif ($httpcode == 200) {
    var_dump($response);
} else {
    echo "Error: HTTP code " . $httpcode;
}

Go

OSS SDK for Go 3.0.2 or later is required.

package main

import (
    "encoding/base64"
    "encoding/json"
    "fmt"
    "io"
    "os"
    "strings"

    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)

type TextData struct {
    RequestId string `json:"RequestId"`
    Output    struct {
        Text         string `json:"Text"`
        FinishReason string `json:"FinishReason"`
    } `json:"Output"`
}

func main() {
    // Obtain access credentials from environment variables.
    // Set OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET, and OSS_SESSION_TOKEN before running this code.
    provider, err := oss.NewEnvironmentVariableCredentialsProvider()
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    // Create an OSSClient instance.
    client, err := oss.New(
        "https://oss-cn-hangzhou.aliyuncs.com", "", "",
        oss.SetCredentialsProvider(&provider),
        oss.AuthVersion(oss.AuthV4),
        oss.Region("cn-hangzhou"),
    )
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // Specify the bucket name. Example: examplebucket.
    bucketName := "examplebucket"
    bucket, err := client.Bucket(bucketName)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    params := make(map[string]interface{})
    params["x-oss-process"] = nil

    // Specify the source text.
    txt := "Ernest Hemingway's \"The Old Man and the Sea\" is a tale of an old fisherman..."
    // Build the processing instruction with URL-safe Base64-encoded content.
    data := fmt.Sprintf("x-oss-process=doc/continue,content_%v", base64.URLEncoding.EncodeToString([]byte(txt)))
    // The object name (example.docx) is a placeholder — its content is not read.
    response, err := bucket.Do("POST", "example.docx", params, nil, strings.NewReader(data), nil)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    defer response.Body.Close()
    jsonData, err := io.ReadAll(response.Body)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    var text TextData
    if err = json.Unmarshal(jsonData, &text); err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    fmt.Printf("RequestId: %v\n", text.RequestId)
    fmt.Printf("Text: %v\n", text.Output.Text)
    fmt.Printf("FinishReason: %v\n", text.Output.FinishReason)
}