助手
扣子 AI 帮助与支持
你好,我是 扣子 文档问答助手 🎉 你在阅读当前文档的过程中,无论对文档概念的解释,还是文档内容方面的疑问,都可以随时向我提问,我会全力为你解答
推荐问题
如何快速了解这个空间的核心内容?
有哪些近期更新的重点文档?
我应该从哪些文档开始阅读?
文档反馈

扣子智能体

更新于: 2026-06-24 15:45:09

本文介绍如何通过扣子罗盘 SDK 和扣子编程 SDK,将扣子编程智能体对话过程的 Trace 数据与扣子罗盘 Trace 数据串联,并上报至扣子罗盘进行观测分析。

功能介绍

扣子编程支持自动上报智能体对话过程的 Trace 数据到扣子罗盘,实现可视化观测,详细说明请参考平台自动上报。同时,扣子罗盘 SDK 提供自定义上报功能,能够上报多种自定义 Trace 数据,如性能数据、执行过程数据、业务数据等。
当你需要将扣子罗盘 SDK 上报的自定义 Trace 数据与扣子编程自动上报的智能体对话过程 Trace 数据串联,形成一个 Trace 调用树时,可参考本文档集成扣子罗盘 SDK 和扣子编程 SDK 来实现。
目前,支持串联如下智能体对话接口的 Trace 数据。

接口

功能

对应 Coze SDK 方法

/v3/chat

向指定智能体发起一次对话。更多信息,请参考发起对话

CozeCli.Chat.Create
CozeCli.Chat.CreateAndPoll
CozeCli.Chat.Stream(流式)

准备工作

目前支持通过 Go SDK 串联 Trace 数据。在进行相关操作前,需要先安装 Go SDK。

  • 安装扣子编程 Go SDK。具体操作,请参考安装 Go SDK
  • 安装扣子罗盘 Go SDK。具体操作,请参考快速开始

步骤一:配置环境变量

在上报 Trace 数据前,你需要正确配置扣子罗盘和扣子编程的环境变量,以确保数据能够正确上报。环境变量配置格式及说明如下:

环境变量

说明

COZELOOP_API_TOKEN

用于设置上报数据时所需的扣子罗盘认证信息,配置为扣子罗盘的个人访问令牌或服务访问令牌,获取访问令牌的步骤,请参考配置个人访问令牌配置服务访问令牌

说明

设置令牌权限时,需要选择罗盘相关权限和Bot 管理-chat权限(用于调用Bot)。

COZELOOP_WORKSPACE_ID

配置为扣子罗盘工作空间 ID。获取空间 ID 的步骤,请参考获取扣子罗盘工作空间 ID

PUBLISHED_BOT_ID

已发布为 API 的智能体 ID。
进入智能体的开发页面,开发页面 URL 中 bot 参数后的数字就是智能体 ID。例如https://www.coze.cn/space/341****/bot/73428668*****,智能体 ID 为73428668*****

说明

确保当前使用的访问密钥已被授予智能体所属空间的 chat 权限。

USER_ID

当前与智能体对话的用户 ID,由使用方自行定义、生成与维护。USER_ID 用于标识对话中的不同用户,不同的用户 ID,其对话的上下文消息、数据库等对话记忆数据互相隔离。如果不需要用户数据隔离,可将此参数固定为一个任意字符串,例如 123abc 等。

说明

出于数据隐私及信息安全等方面的考虑,不建议使用业务系统中定义的用户 ID。

步骤二:上报 Trace

如下示例通过扣子编程 SDK 向智能体发起对话,实现用户与智能体的交互,并集成扣子罗盘 SDK 实现了 Trace 数据串联。Trace 数据串联的具体流程如下:

  1. 通过扣子罗盘 SDK 创建了一个名为 my_type 的 Span 节点。
  2. 将 Span 上下文以 HTTP 请求头形式传递给扣子编程的智能体服务端。
// Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
// SPDX-License-Identifier: MIT

package main

import (
    "context"
    "errors"
    "fmt"
    "io"
    "net/http"
    "os"
    "time"

    "github.com/coze-dev/coze-go"
    "github.com/coze-dev/cozeloop-go"
)

type newTransport struct {
    TraceContextFunc func(ctx context.Context) map[string]string
}

// pass span context to http header
func (n *newTransport) RoundTrip(req *http.Request) (*http.Response, error) {
    if n.TraceContextFunc != nil && len(n.TraceContextFunc(req.Context())) > 0 {
       for key, value := range n.TraceContextFunc(req.Context()) {
          req.Header.Set(key, value)
       }
    }
    return http.DefaultTransport.RoundTrip(req)
}

var httpCli *http.Client
var cozeloopClient cozeloop.Client

func init() {
    var err error
    // init cozeloop client
    // global env COZELOOP_WORKSPACE_ID=your workspace id
    // global env COZELOOP_API_TOKEN=your token
    cozeloopClient, err = cozeloop.NewClient()
    if err != nil {
       panic(err)
    }

    httpCli = &http.Client{Timeout: time.Second * 20}
    httpCli.Transport = &newTransport{
       TraceContextFunc: func(ctx context.Context) map[string]string {
          header, err := cozeloop.GetSpanFromContext(ctx).ToHeader()
          if err != nil {
             fmt.Printf("cozeloop.GetSpanFromContext ToHeader err: %v", err)
             return nil
          }
          return header
       },
    }
}

func main() {
    // Should use the ctx passed down from upstream (for automatic concatenation of traces), and here for simplicity, we will directly use Background
    ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
    defer cancel()

    // Set the following environment variables first.
    // COZELOOP_WORKSPACE_ID=your workspace id, for cozeloop client init by default
    // COZELOOP_API_TOKEN=your token, for cozeloop client init by default
    userID := os.Getenv("USER_ID")
    token := os.Getenv("COZELOOP_API_TOKEN")
    botID := os.Getenv("PUBLISHED_BOT_ID")
    authCli := coze.NewTokenAuth(token)
    cozeApiBase := "https://api.coze.cn" // os.Getenv("COZE_API_BASE")

    // This is a span of cozeloop sdk.
    ctx, span := cozeloopClient.StartSpan(ctx, "my_span", "MyType")

    // Init the Coze client through the access_token.
    cozeCli := coze.NewCozeAPI(authCli,
       coze.WithBaseURL(cozeApiBase),
       coze.WithHttpClient(httpCli),
    )

    // Step one, create chats
    req := &coze.CreateChatsReq{
       BotID:  botID,
       UserID: userID,
       Messages: []*coze.Message{
          coze.BuildUserQuestionText("What can you do?", nil),
       },
    }

    resp, err := cozeCli.Chat.Stream(ctx, req) // Ctx must be transmitted throughout the entire chain, otherwise trace cannot be concatenated
    if err != nil {
       fmt.Printf("Error starting chats: %v\n", err)
       return
    }

    defer resp.Close()
    for {
       event, err := resp.Recv()
       if errors.Is(err, io.EOF) {
          fmt.Println("Stream finished")
          break
       }
       if err != nil {
          fmt.Println(err)
          break
       }
       if event.Event == coze.ChatEventConversationMessageDelta {
          fmt.Print(event.Message.Content)
       } else if event.Event == coze.ChatEventConversationChatCompleted {
          fmt.Printf("Token usage:%d\n", event.Chat.Usage.TokenCount)
       } else {
          fmt.Printf("\n")
       }
    }

    fmt.Printf("done, log:%s\n", resp.Response().LogID())

    span.Finish(ctx) // span finish
    cozeloop.Flush(ctx)
}

步骤三:查看 Trace

上报 Trace 数据后,你可以在扣子罗盘Trace 页面,筛选SDK上报类型,找到目标 Span,查看上报的 Trace 数据。如示下图中所示,扣子罗盘的 my_span Span 已与扣子编程智能体对话过程的 Span 串联,形成一个 Trace 调用树。

Image

Image

示例地址

关于关联扣子智能体对话 Trace 数据的更多 Go SDK 示例代码,请参考 bot_chat