All Products
Search
Document Center

Alibaba Cloud Model Studio:Runs

Last Updated:Mar 23, 2026

A run executes an assistant on a thread. The assistant processes all thread messages and appends its response as a new message.

Prerequisites

Before you begin:

  • An API key configured as an environment variable

  • An existing assistant

  • An existing thread with at least one message

How runs work

queued --> in_progress --> completed
                      \-> requires_action --> (submit tool outputs) --> queued ...
                      \-> failed
                      \-> cancelled
                      \-> expired
                      \-> incomplete
  1. queued: The run is queued for processing.

  2. in_progress: The assistant is processing the thread messages.

  3. requires_action: The assistant invoked a function tool and is waiting for the tool output. Submit the output through the Submit tool outputs endpoint to resume the run.

  4. completed: The run finished successfully. Retrieve the assistant's response from the thread messages.

  5. failed: The run encountered an error. Check last_error for details.

  6. cancelled: The run was cancelled.

  7. expired: The run timed out before completing.

  8. incomplete: The run ended without fully completing.

  9. cancelling: A cancellation is in progress.

Note

No dedicated cancel endpoint exists. Implement cancellation logic in your application if needed.

API operations

Operation

Method

Endpoint

Create a run

POST

/api/v1/threads/{thread_id}/runs

List runs

GET

/api/v1/threads/{thread_id}/runs

Retrieve a run

GET

/api/v1/threads/{thread_id}/runs/{run_id}

Modify a run

POST

/api/v1/threads/{thread_id}/runs/{run_id}

Submit tool outputs

POST

/api/v1/threads/{thread_id}/runs/{run_id}/submit_tool_outputs

Wait for a run

SDK only

N/A

Base URL: https://dashscope-intl.aliyuncs.com/api/v1

Create a run

POST /api/v1/threads/{thread_id}/runs

Starts an assistant on a thread. Supports streaming and non-streaming responses.

Request parameters

Parameter

Type

Required

Description

thread_id

string

Yes

The thread ID (URL path parameter).

assistant_id

string

Yes

The assistant to run.

model

string

No

Overrides the model defined in the assistant. Example: qwen-max, qwen-plus.

instructions

string

No

Overrides the instructions defined in the assistant.

tools

array

No

Overrides the tool list defined in the assistant. See Tool authentication for plug-in auth details.

metadata

object

No

Key-value pairs to attach to the run.

stream

boolean

No

Set to true for streaming responses via server-sent events (SSE). Default: false.

temperature

float

No

Controls randomness (higher = more diverse output).

top_p

float

No

Probability threshold for nucleus sampling.

top_k

integer

No

Size of the candidate token set during sampling.

truncation_strategy

object

No

Message truncation strategy (only last_messages supported). Default: {"type": "last_messages", "last_messages": 10}

workspace

string

No

The workspace ID (required for sub-workspace API keys only).

Tool authentication

For plug-in authentication, include the auth field:

{
  "type": "plugin_type",
  "auth": {
    "type": "user_http",
    "user_token": "<your-bearer-token>"
  }
}

The bearer token is added to plug-in request headers.

Sample request

cURL (non-streaming)

curl -X POST 'https://dashscope-intl.aliyuncs.com/api/v1/threads/thread_cc2a3e9d-436b-482b-91c5-377e0f376506/runs' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $DASHSCOPE_API_KEY" \
  -d '{
    "assistant_id": "asst_46e95014-ccac-435d-b884-c97ac44a94d9",
    "metadata": {}
  }'

cURL (streaming)

curl -X POST 'https://dashscope-intl.aliyuncs.com/api/v1/threads/thread_cc2a3e9d-436b-482b-91c5-377e0f376506/runs' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $DASHSCOPE_API_KEY" \
  -d '{
    "assistant_id": "asst_46e95014-ccac-435d-b884-c97ac44a94d9",
    "metadata": {},
    "stream": true
  }'

Python (streaming)

import dashscope
import os

dashscope.base_http_api_url = 'https://dashscope-intl.aliyuncs.com/api/v1'

stream_iterator = dashscope.Runs.create(
    '<your-thread-id>',
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    assistant_id='<your-assistant-id>',
    stream=True
)

for event, msg in stream_iterator:
    print(event)
    print(msg)

Java (streaming)

import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.InvalidateParameter;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.threads.runs.AssistantStreamMessage;
import com.alibaba.dashscope.threads.runs.RunParam;
import com.alibaba.dashscope.threads.runs.Runs;
import io.reactivex.Flowable;
import com.alibaba.dashscope.utils.Constants;

public class Main {
    static {
        Constants.baseHttpApiUrl = "https://dashscope-intl.aliyuncs.com/api/v1";
    }

    public static void main(String[] args) throws ApiException, NoApiKeyException,
            InputRequiredException, InvalidateParameter, InterruptedException {
        Runs runs = new Runs();
        RunParam runParam = RunParam.builder()
                .apiKey(System.getenv("DASHSCOPE_API_KEY"))
                .assistantId("<your-assistant-id>")
                .stream(true)
                .build();
        Flowable<AssistantStreamMessage> run = runs.createStream("<your-thread-id>", runParam);
    }
}

Non-streaming response

Returns a run object.

{
    "id": "run_3de634fa-75d4-4370-adcf-92ba2a60c396",
    "object": "thread.run",
    "created_at": 1711517598169,
    "thread_id": "thread_cc2a3e9d-436b-482b-91c5-377e0f376506",
    "assistant_id": "asst_46e95014-ccac-435d-b884-c97ac44a94d9",
    "status": "in_progress",
    "model": "qwen-max",
    "instructions": "You are an intelligent assistant. You can call different tools based on user needs to provide answers. Use tools as appropriate.",
    "tools": [
        {"type": "search"},
        {"type": "text_to_image"}
    ],
    "metadata": {},
    "request_id": "225292ff-9843-95d4-8591-b1377c33e2be"
}

Streaming response

Returns a stream of SSE events. Each event has an event field and a data field (JSON object).

Streaming event types

Event

Description

thread.created

A new thread was created (when run creates one).

thread.run.created

The run was created.

thread.run.queued

The run entered the queue.

thread.run.in_progress

The run started processing.

thread.run.step.created

A new run step was created.

thread.run.step.in_progress

A run step started processing.

thread.run.step.delta

Incremental update to a run step (e.g., tool call arguments).

thread.run.step.completed

A run step completed.

thread.message.created

A new message was created.

thread.message.in_progress

Message generation started.

thread.message.delta

Incremental content added to the message.

thread.message.completed

Message generation completed.

thread.run.completed

The run completed (includes token usage in usage field).

done

The stream ended. Data value: [DONE].

Example SSE stream (abbreviated)

event:thread.run.created
data:{"id":"run_04fba6a3-...","object":"thread.run","status":"queued",...}

event:thread.run.in_progress
data:{"id":"run_04fba6a3-...","object":"thread.run","status":"in_progress",...}

event:thread.message.delta
data:{"id":"message_f4f68f6b-...","object":"thread.message.delta","delta":{"content":[{"type":"text","text":{"value":"999 multiplied"}}]}}

event:thread.message.completed
data:{"id":"message_f4f68f6b-...","object":"thread.message","content":[{"type":"text","text":{"value":"999 multiplied by 998 equals 997002."}}],...}

event:thread.run.completed
data:{"id":"run_04fba6a3-...","status":"completed","usage":{"input_tokens":419,"output_tokens":16,"total_tokens":435},...}

event:done
data:[DONE]

SDK response parameters

SDK-specific fields (beyond standard run object):

Parameter

Type

Description

status_code

integer

HTTP status code. 200 indicates success.

code

string

Error code if the request failed. Python SDK only.

message

string

Error details if the request failed. Python SDK only.

List runs

GET /api/v1/threads/{thread_id}/runs

Returns a list of runs for a thread.

Request parameters

Parameter

Type

Required

Description

thread_id

string

Yes

The thread ID (URL path parameter).

limit

integer

No

Maximum number of runs to return. Default: 20.

order

string

No

Sort order by creation time. desc (default) or asc.

Sample request

cURL

curl 'https://dashscope-intl.aliyuncs.com/api/v1/threads/thread_cc2a3e9d-436b-482b-91c5-377e0f376506/runs?limit=20&order=asc' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $DASHSCOPE_API_KEY"

Python

import dashscope
from dashscope import Runs
import os

dashscope.base_http_api_url = 'https://dashscope-intl.aliyuncs.com/api/v1'

runs = Runs.list(
    '<your-thread-id>',
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    limit=1,
    order='desc'
)

Java

import com.alibaba.dashscope.common.GeneralListParam;
import com.alibaba.dashscope.common.ListResult;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.InvalidateParameter;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.threads.runs.Run;
import com.alibaba.dashscope.threads.runs.Runs;
import com.alibaba.dashscope.utils.Constants;

public class Main {
    static {
        Constants.baseHttpApiUrl = "https://dashscope-intl.aliyuncs.com/api/v1";
    }

    public static void main(String[] args) throws ApiException, NoApiKeyException,
            InputRequiredException, InvalidateParameter, InterruptedException {
        Runs runs = new Runs();
        GeneralListParam listRuns = GeneralListParam.builder()
                .apiKey(System.getenv("DASHSCOPE_API_KEY"))
                .build();
        ListResult<Run> run = runs.list("<your-thread-id>", listRuns);
    }
}

Response

{
    "object": "list",
    "data": [
        {
            "id": "run_3de634fa-75d4-4370-adcf-92ba2a60c396",
            "object": "thread.run",
            "created_at": 1711517598169,
            "thread_id": "thread_cc2a3e9d-436b-482b-91c5-377e0f376506",
            "assistant_id": "asst_46e95014-ccac-435d-b884-c97ac44a94d9",
            "status": "completed",
            "model": "qwen-max",
            "tools": [
                {"type": "search"},
                {"type": "text_to_image"}
            ],
            "metadata": {},
            "usage": {
                "prompt_tokens": 66,
                "completion_tokens": 9,
                "total_tokens": 75
            }
        }
    ],
    "first_id": "run_3de634fa-75d4-4370-adcf-92ba2a60c396",
    "last_id": "run_3de634fa-75d4-4370-adcf-92ba2a60c396",
    "has_more": false,
    "request_id": "ff3d2aea-555c-9825-80ca-24029a636641"
}

Response parameters

Parameter

Type

Description

data

array

A list of run objects.

first_id

string

The ID of the first run in the results.

last_id

string

The ID of the last run in the results.

has_more

boolean

Whether more runs are available beyond this page.

Retrieve a run

GET /api/v1/threads/{thread_id}/runs/{run_id}

Returns a single run by ID.

Request parameters

Parameter

Type

Required

Description

thread_id

string

Yes

The thread ID (URL path parameter).

run_id

string

Yes

The run ID (URL path parameter).

Sample request

cURL

curl 'https://dashscope-intl.aliyuncs.com/api/v1/threads/thread_cc2a3e9d-436b-482b-91c5-377e0f376506/runs/run_3de634fa-75d4-4370-adcf-92ba2a60c396' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $DASHSCOPE_API_KEY"

Python

import dashscope
from dashscope import Runs
import os

dashscope.base_http_api_url = 'https://dashscope-intl.aliyuncs.com/api/v1'

run = Runs.retrieve(
    '<your-run-id>',
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    thread_id='<your-thread-id>'
)

Java

import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.InvalidateParameter;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.threads.runs.Run;
import com.alibaba.dashscope.threads.runs.Runs;
import com.alibaba.dashscope.utils.Constants;

public class Main {
    static {
        Constants.baseHttpApiUrl = "https://dashscope-intl.aliyuncs.com/api/v1";
    }

    public static void main(String[] args) throws ApiException, NoApiKeyException,
            InputRequiredException, InvalidateParameter, InterruptedException {
        Runs runs = new Runs();
        String apiKey = System.getenv("DASHSCOPE_API_KEY");
        Run run = runs.retrieve("<your-thread-id>", "<your-run-id>", apiKey);
    }
}

Response

Returns the run object that matches the specified ID.

Modify a run

POST /api/v1/threads/{thread_id}/runs/{run_id}

Updates run metadata.

Request parameters

Parameter

Type

Required

Description

thread_id

string

Yes

The thread ID (URL path parameter).

run_id

string

Yes

The run ID (URL path parameter).

metadata

object

No

Key-value pairs to update.

Sample request

cURL

curl -X POST 'https://dashscope-intl.aliyuncs.com/api/v1/threads/thread_cc2a3e9d-436b-482b-91c5-377e0f376506/runs/run_3de634fa-75d4-4370-adcf-92ba2a60c396' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $DASHSCOPE_API_KEY" \
  -d '{
    "metadata": {
      "user": "abc123"
    }
  }'

Python

import dashscope
from dashscope import Runs
import os

dashscope.base_http_api_url = 'https://dashscope-intl.aliyuncs.com/api/v1'

run = Runs.update(
    '<your-run-id>',
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    thread_id='<your-thread-id>',
    metadata={'newkey': 'newvalue'}
)

Java

import java.util.HashMap;
import java.util.Map;
import com.alibaba.dashscope.common.UpdateMetadataParam;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.InvalidateParameter;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.threads.runs.Run;
import com.alibaba.dashscope.threads.runs.Runs;
import com.alibaba.dashscope.utils.Constants;

public class Main {
    static {
        Constants.baseHttpApiUrl = "https://dashscope-intl.aliyuncs.com/api/v1";
    }

    public static void main(String[] args) throws ApiException, NoApiKeyException,
            InputRequiredException, InvalidateParameter, InterruptedException {
        Runs runs = new Runs();
        Map<String, String> metadata = new HashMap<>();
        metadata.put("key", "value");
        UpdateMetadataParam updateParam = UpdateMetadataParam.builder()
                .metadata(metadata)
                .apiKey(System.getenv("DASHSCOPE_API_KEY"))
                .build();
        Run run = runs.update("<your-thread-id>", "<your-run-id>", updateParam);
    }
}

Response

Returns the updated run object.

Submit tool outputs and continue a run

POST /api/v1/threads/{thread_id}/runs/{run_id}/submit_tool_outputs

When status is requires_action and required_action.type is submit_tool_outputs, submit tool execution results to resume the run.

Important

Submit all pending tool call outputs in one request. Partial submissions are not supported.

How tool output submission works

  1. Create a run. The assistant processes the thread and decides whether to call a tool.

  2. If a function tool is called, status changes to requires_action.

  3. Read required_action.submit_tool_outputs.tool_calls to get the function name, arguments, and tool call ID.

  4. Execute the function in your application and collect the result.

  5. Submit the tool output through this endpoint.

  6. The run resumes processing and eventually reaches a terminal state (completed, failed, or expired).

Request parameters

Parameter

Type

Required

Description

thread_id

string

Yes

The thread ID (URL path parameter).

run_id

string

Yes

The run ID. Must have status requires_action. Specified in the URL path.

tool_outputs

array

Yes

Tool call results to return to the assistant.

tool_outputs[].tool_call_id

string

No

The tool call ID from the required_action response.

tool_outputs[].output

string

Yes

The result from the tool execution.

stream

boolean

No

Set to true for streaming responses. Default: false.

Sample request

cURL (non-streaming)

curl -X POST 'https://dashscope-intl.aliyuncs.com/api/v1/threads/thread_9157dfad-71fd-4add-b7a9-1afa452d2d67/runs/run_99935dbd-e731-4bad-b450-60d9d6bf9a44/submit_tool_outputs' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $DASHSCOPE_API_KEY" \
  -d '{
    "tool_outputs": [
      {
        "tool_call_id": "",
        "output": "rain"
      }
    ]
  }'

cURL (streaming)

curl -X POST 'https://dashscope-intl.aliyuncs.com/api/v1/threads/thread_9157dfad-71fd-4add-b7a9-1afa452d2d67/runs/run_99935dbd-e731-4bad-b450-60d9d6bf9a44/submit_tool_outputs' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $DASHSCOPE_API_KEY" \
  -d '{
    "tool_outputs": [
      {
        "tool_call_id": "",
        "output": "rain"
      }
    ],
    "stream": true
  }'

End-to-end example: function calling with tool output

Complete workflow: create an assistant with a custom function, run it, handle requires_action, submit tool outputs, and retrieve the response.

Python

import json
import sys
from http import HTTPStatus
import dashscope
from dashscope import Assistants, Messages, Runs, Steps, Threads

dashscope.base_http_api_url = 'https://dashscope-intl.aliyuncs.com/api/v1'

def create_assistant():
    # Create an assistant with a custom "big_add" function tool
    assistant = Assistants.create(
        model='qwen-max',
        name='smart helper',
        description='A tool helper.',
        instructions='You are a helpful assistant. When asked a question, use tools wherever possible.',
        tools=[{
            'type': 'tools',
            'tools': {
                'name': 'big_add',
                'description': 'Add to number',
                'parameters': {
                    'type': 'object',
                    'properties': {
                        'left': {
                            'type': 'integer',
                            'description': 'The left operator'
                        },
                        'right': {
                            'type': 'integer',
                            'description': 'The right operator.'
                        }
                    },
                    'required': ['left', 'right']
                }
            }
        }],
    )
    return assistant

def verify_status_code(res):
    if res.status_code != HTTPStatus.OK:
        sys.exit(res.status_code)

if __name__ == '__main__':
    # Step 1: Create the assistant
    assistant = create_assistant()
    verify_status_code(assistant)

    # Step 2: Create a thread
    thread = Threads.create()
    verify_status_code(thread)

    # Step 3: Add a message to the thread
    message = Messages.create(thread.id, content='bigAdd 87787 to 788988737.')
    verify_status_code(message)

    # Step 4: Create a run
    message_run = Runs.create(thread.id, assistant_id=assistant.id)
    verify_status_code(message_run)

    # Step 5: Wait for the run to reach a terminal state
    run_status = Runs.wait(message_run.id, thread_id=thread.id)

    # Step 6: If the run requires tool output, submit it
    if run_status.required_action:
        tool_outputs = [{
            'tool_call_id':
            run_status.required_action.submit_tool_outputs.tool_calls[0].id,
            'output':
            '789076524'
        }]
        run = Runs.submit_tool_outputs(
            message_run.id,
            thread_id=thread.id,
            tool_outputs=tool_outputs
        )
        verify_status_code(run)

        # Step 7: Wait for the run to complete after submitting tool output
        run_status = Runs.wait(message_run.id, thread_id=thread.id)
        verify_status_code(run_status)

    # Step 8: Retrieve the thread messages
    msgs = Messages.list(thread.id)
    print(json.dumps(msgs, default=lambda o: o.__dict__, sort_keys=True, indent=4))

Java

import com.alibaba.dashscope.assistants.Assistant;
import com.alibaba.dashscope.assistants.AssistantParam;
import com.alibaba.dashscope.tools.ToolFunction;
import com.alibaba.dashscope.assistants.Assistants;
import com.alibaba.dashscope.common.GeneralListParam;
import com.alibaba.dashscope.common.ListResult;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.InvalidateParameter;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.threads.AssistantThread;
import com.alibaba.dashscope.threads.ThreadParam;
import com.alibaba.dashscope.threads.Threads;
import com.alibaba.dashscope.threads.messages.Messages;
import com.alibaba.dashscope.threads.messages.TextMessageParam;
import com.alibaba.dashscope.threads.messages.ThreadMessage;
import com.alibaba.dashscope.threads.runs.RequiredAction;
import com.alibaba.dashscope.threads.runs.Run;
import com.alibaba.dashscope.threads.runs.RunParam;
import com.alibaba.dashscope.threads.runs.Runs;
import com.alibaba.dashscope.threads.runs.SubmitToolOutputsParam;
import com.alibaba.dashscope.threads.runs.ToolOutput;
import com.alibaba.dashscope.tools.FunctionDefinition;
import com.alibaba.dashscope.tools.ToolCallBase;
import com.alibaba.dashscope.utils.JsonUtils;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.github.victools.jsonschema.generator.Option;
import com.github.victools.jsonschema.generator.OptionPreset;
import com.github.victools.jsonschema.generator.SchemaGenerator;
import com.github.victools.jsonschema.generator.SchemaGeneratorConfig;
import com.github.victools.jsonschema.generator.SchemaGeneratorConfigBuilder;
import com.github.victools.jsonschema.generator.SchemaVersion;
import com.alibaba.dashscope.tools.ToolCallFunction;
import com.alibaba.dashscope.utils.Constants;

public class AssistantFunctionCall {
    static {
        Constants.baseHttpApiUrl = "https://dashscope-intl.aliyuncs.com/api/v1";
    }

    // Custom function tool: adds two numbers
    public class AddFunctionTool {
        private int left;
        private int right;

        public AddFunctionTool(int left, int right) {
            this.left = left;
            this.right = right;
        }

        public int call() {
            return left + right;
        }
    }

    static ToolFunction buildFunction() {
        SchemaGeneratorConfigBuilder configBuilder =
                new SchemaGeneratorConfigBuilder(
                        SchemaVersion.DRAFT_2020_12, OptionPreset.PLAIN_JSON);
        SchemaGeneratorConfig config = configBuilder
                .with(Option.EXTRA_OPEN_API_FORMAT_VALUES)
                .without(Option.FLATTENED_ENUMS_FROM_TOSTRING)
                .build();
        SchemaGenerator generator = new SchemaGenerator(config);

        ObjectNode jsonSchema = generator.generateSchema(AddFunctionTool.class);

        FunctionDefinition fd = FunctionDefinition.builder()
                .name("add")
                .description("add two numbers")
                .parameters(JsonUtils.parseString(jsonSchema.toString()).getAsJsonObject())
                .build();
        return ToolFunction.builder().function(fd).build();
    }

    // Step 1: Create an assistant with a custom function tool
    static public Assistant createAssistant() throws ApiException, NoApiKeyException {
        AssistantParam assistantParam = AssistantParam.builder()
                .model("qwen-max")
                .description("a helper assistant")
                .name("system")
                .instructions("You are a helpful assistant. When asked a question, use tools wherever possible.")
                .tool(buildFunction())
                .build();
        Assistants assistants = new Assistants();
        return assistants.create(assistantParam);
    }

    static public void run(String assistantId) throws ApiException, NoApiKeyException,
            InvalidateParameter, InputRequiredException, InterruptedException {
        // Step 2: Create a thread
        Threads threads = new Threads();
        AssistantThread assistantThread = threads.create(ThreadParam.builder().build());

        // Step 3: Add a message and create a run
        Messages messages = new Messages();
        TextMessageParam textMessageParam = TextMessageParam.builder()
                .role("user")
                .content("Add 87787 to 788988737.")
                .build();
        ThreadMessage threadMessage = messages.create(assistantThread.getId(), textMessageParam);

        Runs runs = new Runs();
        RunParam runParam = RunParam.builder().assistantId(assistantId).build();
        Run run = runs.create(assistantThread.getId(), runParam);

        // Step 4: Poll until the run reaches a terminal state
        while (true) {
            if (run.getStatus().equals(Run.Status.CANCELLED) ||
                    run.getStatus().equals(Run.Status.COMPLETED) ||
                    run.getStatus().equals(Run.Status.FAILED) ||
                    run.getStatus().equals(Run.Status.REQUIRES_ACTION) ||
                    run.getStatus().equals(Run.Status.EXPIRED)) {
                break;
            } else {
                Thread.sleep(1000);
            }
            run = runs.retrieve(assistantThread.getId(), run.getId());
        }

        // Step 5: Handle requires_action by submitting tool output
        if (run.getStatus().equals(Run.Status.REQUIRES_ACTION)) {
            RequiredAction requiredAction = run.getRequiredAction();
            if (requiredAction.getType().equals("submit_tool_outputs")) {
                ToolCallBase toolCall = requiredAction.getSubmitToolOutputs()
                        .getToolCalls().get(0);
                if (toolCall.getType().equals("function")) {
                    String functionName = ((ToolCallFunction) toolCall).getFunction().getName();
                    String functionId = ((ToolCallFunction) toolCall).getId();
                    String functionArgument = ((ToolCallFunction) toolCall)
                            .getFunction().getArguments();
                    if (functionName.equals("add")) {
                        AddFunctionTool addFunction =
                                JsonUtils.fromJson(functionArgument, AddFunctionTool.class);
                        int sum = addFunction.call();
                        SubmitToolOutputsParam submitToolOutputsParam =
                                SubmitToolOutputsParam.builder()
                                        .toolOutput(ToolOutput.builder()
                                                .toolCallId(functionId)
                                                .content(String.valueOf(sum))
                                                .build())
                                        .build();
                        run = runs.submitToolOutputs(
                                assistantThread.getId(), run.getId(), submitToolOutputsParam);
                    }
                }
            }
        }

        // Step 6: Poll again until the run completes
        while (true) {
            if (run.getStatus().equals(Run.Status.CANCELLED) ||
                    run.getStatus().equals(Run.Status.COMPLETED) ||
                    run.getStatus().equals(Run.Status.FAILED) ||
                    run.getStatus().equals(Run.Status.REQUIRES_ACTION) ||
                    run.getStatus().equals(Run.Status.EXPIRED)) {
                break;
            } else {
                Thread.sleep(1000);
            }
            run = runs.retrieve(assistantThread.getId(), run.getId());
        }

        // Step 7: Retrieve the final messages
        GeneralListParam listParam = GeneralListParam.builder().limit(100L).build();
        ListResult<ThreadMessage> threadMessages =
                messages.list(assistantThread.getId(), listParam);
        for (ThreadMessage msg : threadMessages.getData()) {
            System.out.println(msg);
        }
    }

    public static void main(String[] args) throws ApiException, NoApiKeyException,
            InputRequiredException, InvalidateParameter, InterruptedException {
        Assistant assistant = createAssistant();
        run(assistant.getId());
    }
}

Response

Returns the updated run object. When the run resumes, its status changes from requires_action to queued.

Wait for a run to complete

SDK only. Blocks until run reaches terminal state: cancelled, failed, completed, expired, or requires_action.

Sample code

Python

import dashscope
from dashscope import Runs
import os

dashscope.base_http_api_url = 'https://dashscope-intl.aliyuncs.com/api/v1'

run = Runs.wait(
    '<your-run-id>',
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    thread_id='<your-thread-id>'
)

Java

import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.InvalidateParameter;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.threads.runs.Run;
import com.alibaba.dashscope.threads.runs.Runs;
import com.alibaba.dashscope.utils.Constants;

public class AssistantFunctionCall {
    static {
        Constants.baseHttpApiUrl = "https://dashscope-intl.aliyuncs.com/api/v1";
    }

    public static void main(String[] args) throws ApiException, NoApiKeyException,
            InputRequiredException, InvalidateParameter, InterruptedException {
        Runs runs = new Runs();
        String apiKey = System.getenv("DASHSCOPE_API_KEY");
        Run run = runs.retrieve("<your-thread-id>", "<your-run-id>", apiKey);

        // Poll until the run reaches a terminal state
        while (true) {
            if (run.getStatus().equals(Run.Status.CANCELLED) ||
                    run.getStatus().equals(Run.Status.COMPLETED) ||
                    run.getStatus().equals(Run.Status.FAILED) ||
                    run.getStatus().equals(Run.Status.REQUIRES_ACTION) ||
                    run.getStatus().equals(Run.Status.EXPIRED)) {
                break;
            } else {
                Thread.sleep(1000);
            }
            run = runs.retrieve("<your-thread-id>", run.getId());
        }
    }
}

Request parameters

Parameter

Type

Required

Description

run_id

string

Yes

The run ID.

thread_id

string

Yes

The thread ID.

workspace

string

No

The workspace ID. Required only when the API key belongs to a sub-workspace.

api_key

string

No

The API key. Defaults to the DASHSCOPE_API_KEY environment variable.

Response

Returns the run object in its terminal state.

Run object

Represents a run.

Example

{
    "assistant_id": "asst_xxxx",
    "cancelled_at": null,
    "completed_at": null,
    "created_at": 1735026246751,
    "expires_at": null,
    "failed_at": null,
    "file_ids": [],
    "id": "run_xxxx",
    "instructions": "you are a helpful assistant",
    "last_error": null,
    "max_tokens": null,
    "metadata": {},
    "model": "qwen-plus",
    "object": "thread.run",
    "request_id": "req_xxxx",
    "required_action": null,
    "started_at": null,
    "status": "in_progress",
    "temperature": null,
    "thread_id": "thread_xxxx",
    "tool_choice": "auto",
    "tools": [],
    "top_k": null,
    "top_p": null,
    "truncation_strategy": null,
    "usage": null
}

Attributes

Attribute

Type

Description

id

string

Unique identifier (format: run_*).

object

string

Object type (always thread.run).

assistant_id

string

The assistant associated with this run.

thread_id

string

The thread this run belongs to.

status

string

Current status: queued, in_progress, requires_action, cancelling, cancelled, failed, completed, incomplete, or expired.

model

string

The model used for this run.

instructions

string

The instructions the assistant followed during this run.

tools

array

The tools available to the assistant during this run.

metadata

map

Up to 16 key-value pairs (keys: max 64 chars, values: max 512 chars).

required_action

object

Action needed to proceed (e.g., submit tool outputs). null unless status is requires_action.

last_error

object

Last error during run (null if none).

usage

object

Token usage (input_tokens and output_tokens).

created_at

integer

Unix timestamp (ms) when created.

started_at

integer

Unix timestamp (ms) when started processing.

completed_at

integer

Unix timestamp (ms) when completed.

cancelled_at

integer

Unix timestamp (ms) when cancelled.

failed_at

integer

Unix timestamp (ms) when failed.

expired_at

integer

Unix timestamp (ms) when expired.

FAQ

Q: How do I cancel a run that is in progress?

No dedicated cancel endpoint. Implement cancellation in your application.

Error codes

For failed API calls, see Error messages.