All Products
Search
Document Center

:Praktik terbaik untuk mengintegrasikan DAS Agent dengan Chat API

Last Updated:Aug 29, 2026

Chat API adalah antarmuka asinkron untuk DAS Agent yang mendukung tanya jawab berbasis pengetahuan, diagnostik kinerja, dan Percakapan multi-putaran. API ini mengembalikan proses penalaran agen dan jawaban akhir sebagai aliran Server-Sent Events (SSE). Topik ini menjelaskan cara mengintegrasikan Chat API menggunakan SDK Java, Python, dan Go, lengkap dengan contoh parsing event SSE dan Percakapan multi-putaran.

Prasyarat

  • DAS Agent telah diaktifkan, wilayah instans terkelola sesuai dengan negara atau wilayah DAS Agent, dan instans tersebut telah ditautkan ke DAS Agent.

  • Alibaba Cloud DAS SDK versi terbaru telah diinstal.

  • Wilayah diatur ke cn-shanghai dan titik akhir diatur ke das.cn-shanghai.aliyuncs.com.

  • Variabel lingkungan ALIBABA_CLOUD_ACCESS_KEY_ID dan ALIBABA_CLOUD_ACCESS_KEY_SECRET telah dikonfigurasi, atau rantai kredensial default Alibaba Cloud digunakan.

Catatan

Chat API adalah antarmuka berbayar yang dikenai biaya berdasarkan jumlah karakter input dan output. Untuk informasi selengkapnya, lihat penagihan DAS Agent.

Event inti

Aliran SSE mengikuti protokol ag-ui. Tabel berikut menjelaskan jenis event utama.

Jenis Peristiwa

Bidang kunci

Deskripsi

RUN_STARTED

RunId

Menunjukkan bahwa tugas telah dimulai. Menandai awal sesi chat.

RUN_FINISHED

RunId

Menunjukkan bahwa tugas telah selesai. Tidak ada event tambahan yang dihasilkan setelah event ini.

TEXT_MESSAGE_START

MessageId, Role

Menandai awal pesan teks. Role=user menggemakan input pengguna dan dapat diabaikan. Role=assistant menunjukkan output model.

TEXT_MESSAGE_CONTENT

MessageId, Delta

Berisi fragmen teks incremental. Gabungkan nilai Delta dari event yang memiliki MessageId yang sama untuk mendapatkan pesan lengkap.

TEXT_MESSAGE_END

MessageId

Menandai akhir pesan teks.

ACTIVITY_DELTA

ActivityType, Patch

Event heartbeat atau status dari agen, seperti waiting_for_agent_thinking. Event ini biasanya dapat diabaikan.

TOOL_CALL_START

ToolCallId, ToolCallName, ParentMessageId

Menunjukkan bahwa agen telah memulai pemanggilan tool, seperti das_api.

TOOL_CALL_ARGS

ToolCallId, Delta

Mengalirkan parameter tool sebagai fragmen teks JSON. Gabungkan nilai Delta untuk ToolCallId yang sama untuk mendapatkan set parameter lengkap.

TOOL_CALL_END

ToolCallId

Menunjukkan bahwa semua parameter tool telah dikirim dan tool akan segera dieksekusi.

TOOL_CALL_RESULT

ToolCallId, Content, MessageId

Mengembalikan hasil eksekusi tool. Bidang Content berisi teks hasil.

Urutan event khas

Contoh berikut menggunakan prompt "Apply SQL throttling to instance rm-uf63bopu77b*******" untuk menggambarkan urutan lengkap event SSE.

1. Mulai tugas

Setelah server menerima permintaan, server mengirim event RUN_STARTED yang menandai awal sesi. Klien dapat menggunakan event ini untuk memulai pengatur waktu atau menginisialisasi UI.

{"Type":"RUN_STARTED","RunId":"58abc22e-5742-4e9b-802e-5f060a0ca2e3"}

2. Penggemakan input pengguna (dapat diabaikan)

Server menggemakan pesan pengguna sebagai pesan teks dengan Role=user. Klien biasanya tidak perlu menampilkan pesan ini. Filter berdasarkan Role untuk melewatinya.

{"Type":"TEXT_MESSAGE_START","Role":"user","MessageId":"20d2bc27-1644-47e5-8816-b0e764e84a6e"}
{"Type":"TEXT_MESSAGE_CONTENT","MessageId":"20d2bc27-1644-47e5-8816-b0e764e84a6e","Delta":"Apply SQL throttling to instance rm-uf63bopu77b*******"}
{"Type":"TEXT_MESSAGE_END","MessageId":"20d2bc27-1644-47e5-8816-b0e764e84a6e"}

3. Heartbeat agen (dapat diabaikan)

Selama fase penalaran model, event ACTIVITY_DELTA berfungsi sebagai sinyal heartbeat. Lewati event ini di klien.

{"Type":"ACTIVITY_DELTA","ActivityType":"waiting_for_agent_thinking","Patch":[],"MessageId":""}

4. Output analisis agen (Role=assistant)

Model mengalirkan penalarannya melalui event TEXT_MESSAGE_CONTENT.Delta. Gabungkan nilai Delta untuk MessageId yang sama guna menyusun respons lengkap.

{"Type":"TEXT_MESSAGE_START","Role":"assistant","MessageId":"36aaafdb-ea7f-4475-bad7-136e12117959"}
{"Type":"TEXT_MESSAGE_CONTENT","MessageId":"36aaafdb-ea7f-4475-bad7-136e12117959","Delta":"I need to check the SQL execution status of this instance first to determine which SQL statements require throttling. Let me query the recent SQL audit logs.\n\n"}
{"Type":"TEXT_MESSAGE_END","MessageId":"36aaafdb-ea7f-4475-bad7-136e12117959"}

5. Pemanggilan tool oleh agen

Ketika agen memanggil tool eksternal seperti das_api, event mengikuti urutan berikut: TOOL_CALL_START → beberapa TOOL_CALL_ARGSTOOL_CALL_ENDTOOL_CALL_RESULT.

Awal Pemanggilan

{"Type":"TOOL_CALL_START","ToolCallId":"call_0fd4d07290b54dd7b7064cc2","ToolCallName":"das_api","ParentMessageId":"36aaafdb-ea7f-4475-bad7-136e12117959"}

Parameter streaming

Beberapa event TOOL_CALL_ARGS.Delta harus digabungkan berdasarkan ToolCallId. Setelah digabungkan, uraikan hasilnya sebagai objek JSON lengkap:

{
  "command": "execute",
  "api_name": "getdassqlloghotdata",
  "parameters": {
    "instance_id": "rm-uf63bopu77b*******",
    "start": "2026-03-05T15:54:16+08:00",
    "end": "2026-03-05T16:54:16+08:00",
    "max_records_per_page": 10,
    "include_fields": ["sql_text", "execution_count", "avg_consume"],
    "security_risk": "LOW"
  }
}

Akhir parameter dan hasil eksekusi

{"Type":"TOOL_CALL_END","ToolCallId":"call_0fd4d07290b54dd7b7064cc2"}
{"Type":"TOOL_CALL_RESULT","ToolCallId":"call_0fd4d07290b54dd7b7064cc2","MessageId":"36aaafdb-ea7f-4475-bad7-136e12117959","Content":"API call succeeded. Response: ..."}

6. Akhir tugas

Event RUN_FINISHED menunjukkan akhir aliran SSE. Klien dapat menghentikan pengatur waktu dan menutup koneksi.

{"Type":"RUN_FINISHED","RunId":"58abc22e-5742-4e9b-802e-5f060a0ca2e3"}

Contoh SDK

Java

Dependensi Maven

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>alibabacloud-das20200116</artifactId>
    <version>2.0.0</version>
</dependency>

Kode contoh

import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
import com.aliyun.sdk.gateway.pop.Configuration;
import com.aliyun.sdk.gateway.pop.auth.SignatureVersion;
import com.aliyun.sdk.service.das20200116.AsyncClient;
import com.aliyun.sdk.service.das20200116.models.ChatRequest;
import com.aliyun.sdk.service.das20200116.models.ChatResponseBody;
import darabonba.core.ResponseIterable;
import darabonba.core.client.ClientOverrideConfiguration;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class ChatSample {

    private static AsyncClient createClient() {
        StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder()
                .accessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
                .accessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"))
                .build());

        return AsyncClient.builder()
                .region("cn-shanghai")
                .credentialsProvider(provider)
                .serviceConfiguration(Configuration.create().setSignatureVersion(SignatureVersion.V3))
                .overrideConfiguration(ClientOverrideConfiguration.create().setProtocol("HTTPS")
                        .setEndpointOverride("das.cn-shanghai.aliyuncs.com"))
                .build();
    }

    private static String buildMessage(String text) {
        String escaped = text.replace("\\", "\\\\").replace("\"", "\\\"");
        return String.format(
                "{\"id\":\"%s\",\"role\":\"user\",\"content\":[{\"type\":\"text\",\"text\":\"%s\"}]}",
                UUID.randomUUID(),
                escaped);
    }

    private static ChatRequest buildRequest(String text, String sessionId, String agentId, String summary) {
        ChatRequest.Builder builder = ChatRequest.builder().message(buildMessage(text));
        if (sessionId != null && !sessionId.isEmpty()) {
            builder.sessionId(sessionId);
        }
        if (agentId != null && !agentId.isEmpty()) {
            builder.agentId(agentId);
        }
        if (summary != null && !summary.isEmpty()) {
            builder.summary(summary);
        }
        return builder.build();
    }

    private static void run(String text, String sessionId, String agentId, String summary) throws Exception {
        AsyncClient client = createClient();
        ChatRequest request = buildRequest(text, sessionId, agentId, summary);

        ResponseIterable<ChatResponseBody> iterable = client.chatWithResponseIterable(request);
        for (ChatResponseBody event : iterable) {
            String delta = event.getDelta();
            String content = event.getContent();
            String activity = event.getActivityType();
            String extName = event.getName();
            Object extValue = event.getValue();

            if (delta != null && !delta.isEmpty()) {
                System.out.print(delta);
            } else if (content != null && !content.isEmpty()) {
                System.out.println();
                System.out.println("[Content] " + content);
            } else if (activity != null && !activity.isEmpty()) {
                System.out.println();
                System.out.println("[Activity] " + activity);
                System.out.println();
            }

            if ("summary".equals(extName) && extValue != null) {
                System.out.println();
                System.out.println("[Summary] " + extValue);
            }
        }
        System.out.println();
        client.close();
    }

    private static class Args {
        String query = "Describe DAS Agent in about 1000 words";
        String sessionId;
        String agentId;
        String summary;
    }

    private static Args parseArgs(String[] argv) {
        Args args = new Args();
        List<String> positional = new ArrayList<>();
        for (int i = 0; i < argv.length; i++) {
            switch (argv[i]) {
                case "--session-id":
                    args.sessionId = argv[++i];
                    break;
                case "--agent-id":
                    args.agentId = argv[++i];
                    break;
                case "--summary":
                    args.summary = argv[++i];
                    break;
                default:
                    positional.add(argv[i]);
                    break;
            }
        }
        if (!positional.isEmpty()) {
            args.query = String.join(" ", positional);
        }
        return args;
    }

    public static void main(String[] argv) throws Exception {
        Args args = parseArgs(argv);
        run(args.query, args.sessionId, args.agentId, args.summary);
    }
}

Run the command

mvn -q exec:java -Dexec.mainClass=ChatSample -Dexec.args="'Describe DAS Agent in about 1000 words'"

Python

Instal SDK

pip3 install alibabacloud_das20200116==3.0.0

Kode contoh

# -*- coding: utf-8 -*-

import argparse
import json
import sys
import uuid

from alibabacloud_credentials.client import Client as CredentialClient
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_tea_openapi.client import Client as OpenApiClient
from alibabacloud_tea_util import models as util_models
from alibabacloud_tea_util.client import Client as UtilClient


class ChatSample:

    @staticmethod
    def create_client() -> OpenApiClient:
        credential = CredentialClient()
        config = open_api_models.Config(credential=credential)
        config.endpoint = 'das.cn-shanghai.aliyuncs.com'
        return OpenApiClient(config)

    @staticmethod
    def create_api_info() -> open_api_models.Params:
        return open_api_models.Params(
            action='Chat',
            version='2020-01-16',
            protocol='HTTPS',
            pathname='/chat',
            method='POST',
            auth_type='AK',
            style='RPC',
            req_body_type='json',
            body_type='sse',
        )

    @staticmethod
    def build_message(text: str) -> str:
        message = {
            'id': str(uuid.uuid4()),
            'role': 'user',
            'content': [{'type': 'text', 'text': text}],
        }
        return json.dumps(message, ensure_ascii=False)

    @staticmethod
    def build_request(
        text: str,
        session_id: str = None,
        agent_id: str = None,
        summary: str = None,
    ) -> open_api_models.OpenApiRequest:
        query = {'Message': ChatSample.build_message(text)}
        if not UtilClient.is_unset(session_id):
            query['SessionId'] = session_id
        if not UtilClient.is_unset(agent_id):
            query['AgentId'] = agent_id
        if not UtilClient.is_unset(summary):
            query['Summary'] = summary
        return open_api_models.OpenApiRequest(query=query, headers={})

    @staticmethod
    def parse_event_data(event) -> dict:
        if not hasattr(event, 'data'):
            return {}
        data = event.data
        if isinstance(data, str):
            try:
                data = json.loads(data)
            except json.JSONDecodeError:
                return {}
        return data if isinstance(data, dict) else {}

    @staticmethod
    def run(
        text: str,
        session_id: str = None,
        agent_id: str = None,
        summary: str = None,
    ) -> None:
        client = ChatSample.create_client()
        params = ChatSample.create_api_info()
        runtime = util_models.RuntimeOptions()
        request = ChatSample.build_request(text, session_id, agent_id, summary)

        response = client.call_sseapi(params, request, runtime)
        full_content = []

        for res in response:
            data = ChatSample.parse_event_data(res.event)
            if not data:
                continue

            activity = data.get('ActivityType')
            delta = data.get('Delta')
            content = data.get('Content')
            ext_name = data.get('Name')
            ext_value = data.get('Value')

            if delta:
                print(delta, end='', flush=True)
                full_content.append(delta)
            elif content and not delta:
                print(f"\n[Content] {content}", flush=True)
            elif activity:
                print(f"\n[Activity] {activity}", file=sys.stderr, flush=True)

            if ext_name == 'summary' and ext_value:
                print(f"\n[Summary] {ext_value}", flush=True)

        if full_content:
            print()


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(description='DAS Chat API sample')
    parser.add_argument(
        'query',
        nargs='?',
        default='Describe DAS Agent in about 1000 words',
        help='User query',
    )
    parser.add_argument('--session-id', dest='session_id', help='Session ID (UUID)')
    parser.add_argument('--agent-id', dest='agent_id', help='Agent ID')
    parser.add_argument('--summary', choices=['true', 'false'], help='Whether to return summary information')
    return parser.parse_args()


if __name__ == '__main__':
    args = parse_args()
    ChatSample.run(
        text=args.query,
        session_id=args.session_id,
        agent_id=args.agent_id,
        summary=args.summary,
    )

Perintah jalankan

# Percakapan satu putaran
python3 chat_sample.py "Describe DAS Agent in about 1000 words"

# Percakapan multi-putaran (berikan SessionId dan AgentId)
python3 chat_sample.py "Tell me more about slow query analysis" \
    --session-id 123e4567-e89b-12d3-a456-xxxxxxxxxxxx \
    --agent-id ag-472T0DxtmjIxxxxx \
    --summary true

Go

Instal SDK

go mod init das_agent_chat_demo
go get github.com/alibabacloud-go/darabonba-openapi/v2/client
go get github.com/alibabacloud-go/tea-utils/v2/service
go get github.com/alibabacloud-go/tea/tea
go get github.com/google/uuid

Kode contoh

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"os"
	"strings"

	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	openapiutil "github.com/alibabacloud-go/darabonba-openapi/v2/utils"
	"github.com/alibabacloud-go/tea/dara"
	"github.com/alibabacloud-go/tea/tea"
	"github.com/google/uuid"
)

func createClient() (*openapi.Client, error) {
	config := &openapi.Config{
		AccessKeyId:     tea.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")),
		AccessKeySecret: tea.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")),
		Endpoint:        tea.String("das.cn-shanghai.aliyuncs.com"),
	}
	return openapi.NewClient(config)
}

func createAPIInfo() *openapi.Params {
	return &openapi.Params{
		Action:      tea.String("Chat"),
		Version:     tea.String("2020-01-16"),
		Protocol:    tea.String("HTTPS"),
		Pathname:    tea.String("/chat"),
		Method:      tea.String("POST"),
		AuthType:    tea.String("AK"),
		Style:       tea.String("RPC"),
		ReqBodyType: tea.String("json"),
		BodyType:    tea.String("sse"),
	}
}

func buildMessage(text string) (string, error) {
	payload := map[string]interface{}{
		"id":   uuid.NewString(),
		"role": "user",
		"content": []map[string]string{
			{"type": "text", "text": text},
		},
	}
	bs, err := json.Marshal(payload)
	if err != nil {
		return "", err
	}
	return string(bs), nil
}

func buildRequest(text, sessionID, agentID, summary string) (*openapi.OpenApiRequest, error) {
	msg, err := buildMessage(text)
	if err != nil {
		return nil, err
	}
	query := map[string]interface{}{
		"Message": msg,
	}
	if sessionID != "" {
		query["SessionId"] = sessionID
	}
	if agentID != "" {
		query["AgentId"] = agentID
	}
	if summary != "" {
		query["Summary"] = summary
	}
	return &openapi.OpenApiRequest{
		Query:   openapiutil.Query(query),
		Headers: map[string]*string{},
	}, nil
}

func parseEventData(raw *string) map[string]interface{} {
	if raw == nil || *raw == "" {
		return nil
	}
	var data map[string]interface{}
	if err := json.Unmarshal([]byte(*raw), &data); err != nil {
		return nil
	}
	return data
}

func run(text, sessionID, agentID, summary string) error {
	client, err := createClient()
	if err != nil {
		return err
	}
	params := createAPIInfo()
	request, err := buildRequest(text, sessionID, agentID, summary)
	if err != nil {
		return err
	}
	runtime := &dara.RuntimeOptions{}

	sseChan := make(chan *openapi.SSEResponse, 100)
	errChan := make(chan error, 1)
	go client.CallSSEApi(params, request, runtime, sseChan, errChan)

	for event := range sseChan {
		if event.Event == nil {
			continue
		}
		data := parseEventData(event.Event.Data)
		if data == nil {
			continue
		}

		delta, _ := data["Delta"].(string)
		content, _ := data["Content"].(string)
		activity, _ := data["ActivityType"].(string)
		extName, _ := data["Name"].(string)
		extValue := data["Value"]

		switch {
		case delta != "":
			fmt.Print(delta)
		case content != "":
			fmt.Println()
			fmt.Println("[Content]", content)
		case activity != "":
			fmt.Fprintln(os.Stderr, "[Activity]", activity)
		}

		if extName == "summary" && extValue != nil {
			fmt.Println()
			fmt.Println("[Summary]", extValue)
		}
	}
	fmt.Println()
	if err := <-errChan; err != nil {
		return err
	}
	return nil
}

func main() {
	fs := flag.NewFlagSet("chat_sample", flag.ExitOnError)
	sessionID := fs.String("session-id", "", "Session ID (UUID)")
	agentID := fs.String("agent-id", "", "Agent ID")
	summary := fs.String("summary", "", "Whether to return summary (true/false)")
	fs.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [query] [--session-id ID] [--agent-id ID] [--summary true|false]\n", os.Args[0])
		fs.PrintDefaults()
	}
	if err := fs.Parse(os.Args[1:]); err != nil {
		os.Exit(2)
	}

	query := "Describe DAS Agent in about 1000 words"
	if fs.NArg() > 0 {
		query = strings.Join(fs.Args(), " ")
	}

	if err := run(query, *sessionID, *agentID, *summary); err != nil {
		fmt.Fprintln(os.Stderr, "request failed:", err)
		os.Exit(1)
	}
}

Run the command

# Percakapan satu putaran
go run chat_sample.go "Describe DAS Agent in about 1000 words"

# Percakapan multi-putaran (berikan SessionId dan AgentId)
go run chat_sample.go "Tell me more about slow query analysis" \
    --session-id 123e4567-e89b-12d3-a456-xxxxxxxxxxxx \
    --agent-id ag-472T0DxtmjIxxxxx \
    --summary true

Catatan penggunaan

  • Untuk Percakapan multi-putaran, selalu berikan SessionId yang sama. Jika tidak, model tidak dapat mempertahankan konteks dari putaran sebelumnya.

  • Aliran SSE berisi event heartbeat (ACTIVITY_DELTA). Lewati event ini di klien.

  • Chat API dikenai biaya berdasarkan jumlah karakter input dan output. Selama pengembangan, mulailah dengan kueri uji sederhana untuk menghindari biaya tak terduga.