> ## Documentation Index
> Fetch the complete documentation index at: https://docs.coze.cn/llms.txt
> Use this file to discover all available pages before exploring further.

本文指导你如何安装并使用扣子罗盘 Go SDK 进行 Trace 数据上报、Prompt 拉取等操作。 
## 准备工作 {#6a8a6113}
### 环境准备 {#eef3989e}
扣子罗盘 Go SDK 适用于 Go 1.8 及以上版本。
安装 Go SDK 之前，执行以下命令确认你已安装 1.8 及以上版本的 Go。 
```Go
# 查看 Go 版本   
go version 
 
# 回显信息显示已安装 1.18.10 版本 
go version go 1.18.10 darwin/amd64 
```

### SDK 授权 {#bc656170}
在使用扣子罗盘 Go SDK 前，确保你已经完成了授权。详情请参考[SDK 鉴权](/cozeloop/authentication-for-sdk)。
## 安装扣子罗盘 Go SDK {#c1646103}
执行以下命令安装扣子罗盘 Go SDK。
```Go
go get github.com/coze-dev/cozeloop-go
```

默认直接安装最新版本的 SDK。如果你想使用历史版本，单击[此处](https://github.com/coze-dev/cozeloop-go/blob/main/CHANGLOG.md)查看历史版本记录和 README。
## 初始化扣子罗盘 SDK {#d200b0f8}
初始化扣子罗盘 Client 之后，才可以访问  SDK 提供的 API。
初始化时推荐通过环境变量动态获取访问密钥，以免硬编码引发数据安全风险。 设置完成环境变量后，你可以直接访问 SDK API 实现相应功能。
以下示例代码展示了如何使用扣子罗盘 SDK 创建并上报一个 Span。
:::tip 说明
该示例中使用了 PAT 授权方式，在生产环境中推荐使用安全性更高的 OAuth 授权方式，详情参考[配置 OAuth JWT 授权](/cozeloop/authentication-for-sdk#997bf42b)。
:::
```Go
import (
    "context"
    
    "github.com/coze-dev/cozeloop-go"
)

func main() {
    // 设置相关环境变量
    // COZELOOP_WORKSPACE_ID=your workspace id
    // COZELOOP_API_TOKEN=your token
    
    // 直接调用api
    ctx, span := cozeloop.StartSpan(context.Background(), "first_span", "custom")
    span.Finish(ctx)

    // 程序退出前，需要调用Close方法，否则可能造成trace数据上报丢失。Close后无法再执行任何操作。
    cozeloop.Close(ctx)
}
```

你也可以通过创建 client 进行更多定制化配置。
:::tip 说明
client 是协程安全的，一般一个进程中仅需要创建一个 client 即可。
:::
```Go
import (
    "context"
    
    "github.com/coze-dev/cozeloop-go"
)

func main() {
    // 设置相关环境变量
    // COZELOOP_WORKSPACE_ID=your workspace id
    // COZELOOP_API_TOKEN=your token
    
    // 创建client
    client, err := cozeloop.NewClient()
    if err != nil {
       panic(err)
    }

    // 通过client调用api
    ctx, span := client.StartSpan(context.Background(), "first_span", "custom")
    span.Finish(ctx)
    
    // 程序退出前，需要调用Close方法，否则可能造成trace数据上报丢失。Close后无法再执行任何操作。
    client.Close(ctx)
}
```

## 观测示例代码 {#6b5a289a}
### Eino {#4a8c980e}
推荐使用 [Eino](https://github.com/cloudwego/eino) 框架进行 Go 语言 AI 应用的开发。扣子罗盘基于 Eino 的 callback 机制，提供了一键集成能力，能够自动完成 AI 应用的 Trace 数据上报。
#### 安装 Go SDK {#d64a1f6f}
```Go
go get github.com/cloudwego/eino-ext/callbacks/cozeloop
```

#### 示例代码 {#32ffd000}
以下示例代码展示了如何在 Eino 框架中集成扣子罗盘 SDK，通过回调机制自动记录和追踪程序运行状态。

1. 首先，通过环境变量的方式完成授权。
   该示例中使用了 PAT 授权方式，你可以使用 OAuth 方式进行授权。具体说明，请参考[SDK 鉴权](/cozeloop/authentication-for-sdk)。
2. 创建扣子罗盘客户端。
3. 使用 `defer` 确保程序退出前正确关闭客户端。
4. 创建扣子罗盘的回调处理器（handler）。
5. 将处理器注册到 Eino 框架的全局回调系统中。

```Go
import (
    "context"

    ccb "github.com/cloudwego/eino-ext/callbacks/cozeloop"
    "github.com/cloudwego/eino/callbacks"
    "github.com/coze-dev/cozeloop-go"
)

func main() {
    // 设置相关环境变量
    // COZELOOP_WORKSPACE_ID=your workspace id
    // COZELOOP_API_TOKEN=your token
    ctx := context.Background()
    client, err := cozeloop.NewClient()
    if err != nil {
       panic(err)
    }
    defer client.Close(ctx)
    // 在服务 init 时 once 调用
    handler := ccb.NewLoopHandler(client)
    callbacks.AppendGlobalHandlers(handler)
}
```

### Low-Level API {#28780e38}
你也可以通过扣子罗盘 SDK 提供的 low-level API，手动完成 Trace 数据的上报。
:::tip 说明
Low-level API 是更底层的编程接口，提供基础功能的直接访问，需要开发者手动处理更多细节，但能实现更灵活的控制和定制化需求。
:::
#### Root Span 上报 {#c03e1ca1}
在处理用户请求时，建议为每个请求创建一个完整的 Trace 链路：从服务入口处创建 root span，记录用户输入、系统响应和关键业务标识（如请求ID、用户ID等），便于后续进行链路追踪和性能分析。当请求处理完成时，调用 `Finish` 方法结束追踪。
以下示例代码展示了如何使用扣子罗盘 SDK 创建一个完整的请求追踪链路（Trace）。
```Go
import (
    "context"

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

func handler(ctx context.Context, input string) (string, error) {
    // 开启span
    ctx, span := cozeloop.StartSpan(ctx, "{your_span_name}", "{your_span_type}")
    // 设置用户输入
    span.SetInput(ctx, input)
    // 设置相关业务id，可以使用Baggage能力将这些id全链路透传，减少重复代码，便于在平台上自由检索
    span.SetUserIDBaggage(ctx, "{user_id}")
    span.SetMessageIDBaggage(ctx, "{message_id}")
    
    // 执行业务逻辑
    output, err := DoSomething(ctx, input) 
    if err != nil {
       // 设置错误信息
       span.SetStatusCode(ctx, your_error_code)   
       span.SetError(ctx, err)
    } else {
       // 设置系统输出
       span.SetOutput(ctx, output)
    }
    // 如果使用流式返回，记录首Token返回的微秒时间戳，SDK会自动计算首Token耗时
    span.SetStartTimeFirstResp(ctx, {start_time_first_resp})

    // span上报
    span.Finish(ctx)
}
```

#### Model Span 上报 {#9ec0f814}
模型调用往往是最关键的节点，在模型调用前后，上报 Model Span。`span_type`应该使用`model`，建议使用 `spec` 公共包中的 `ModelInput` 和 `ModelOutput` 记录input和output，以便在平台获得更好的体验。
在进行模型调用时，建议创建专门的 Model Span 来追踪这个关键环节。以下示例代码展示了如何使用扣子罗盘 SDK 创建一个完整的模型调用追踪：

1. 创建 Model Span 时使用`tracespec.VModelSpanType`作为类型标识。
2. 记录模型调用的完整上下文：
   * 输入信息：使用 `tracespec.ModelInput`记录系统提示词和用户输入。
   * 模型信息：记录模型提供商、模型名称和调用参数。
   * Prompt 信息：关联使用的 Prompt Key 和版本。
3. 调用完成后记录：
   * 输出内容：使用`tracespec.ModelOutput`记录模型响应。
   * 性能指标：记录输入输出的 Token 数量。
   * 对于流式响应：记录首 Token 时间戳以计算响应延迟

以下是完整的 Model Span 上报示例代码。
```Go
import (
    "context"

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

var (
    // 初始化client，打开prompt trace上报开关
    client, _ = cozeloop.NewClient(cozeloop.WithPromptTrace(true))
)

func CallLLM(ctx context.Context, prompt *entity.Prompt) error {
    // SpanType使用model
    ctx, span := client.StartSpan(ctx, "{your_span_name}", tracespec.VModelSpanType)
    defer span.Finish(ctx)

    span.SetInput(ctx, tracespec.ModelInput{
       Messages: []*tracespec.ModelMessage{
          {
             Role:    tracespec.VRoleSystem,
             Content: "{system_prompt}",
          },
          {
             Role:    tracespec.VRoleUser,
             Content: "{user_prompt}",
          },
       },
    })
    // 设置模型提供商和模型名称
    span.SetModelProvider(ctx, "{model_provider}")
    span.SetModelName(ctx, "{model_name}")
    // 关联PromptKey和Version
    span.SetPrompt(ctx, *prompt)
    // 设置Temperature, MaxTokens等其他参数
    span.SetModelCallOptions(ctx, tracespec.ModelCallOption{})

    // 使用任意方式调用大模型
    // ...

    span.SetOutput(ctx, tracespec.ModelOutput{
       Choices: []*tracespec.ModelChoice{
          {
             Message: &tracespec.ModelMessage{
                Role:    tracespec.VRoleAssistant,
                Content: "{model_response}",
             },
          },
       },
    })
    // 设置InputTokens和OutputTokens，SDK会自动计算TotalTokens
    span.SetInputTokens(ctx, {input_tokens})
    span.SetOutputTokens(ctx, {output_tokens})
    // 如果使用流式返回，记录首Token返回的微秒时间戳，SDK会自动计算首Token耗时
    span.SetStartTimeFirstResp(ctx, {start_time_first_resp})
    return nil
}
```

#### 自定义 Span 上报 {#eb6da55a}
你可以在任何重要的业务节点创建自定义 span，通过设置以下信息进行全面追踪：

* 基础信息：自定义 span 名称和类型
* 业务数据：记录输入输出内容
* 自定义标签：通过 SetTags 添加需要追踪的特定信息
* 执行状态：记录状态码和错误信息

这种灵活的追踪方式让您能够根据业务需求，精确监控和分析任何关键流程。
以下示例代码展示了如何创建自定义 Span。
```Go
import (
    "context"
    
    "github.com/coze-dev/cozeloop-go"
)

var (
    // 初始化client，打开prompt trace上报开关
    client, _ = cozeloop.NewClient(cozeloop.WithPromptTrace(true))
)

func CustomFunc(ctx context.Context) error {
    ctx, span := client.StartSpan(ctx, "{your_span_name}", "{your_span_type}")
    span.SetInput(ctx, "{your_input}")
    // 设置自定义tag
    span.SetTags(ctx, map[string]any{})

    // 执行业务逻辑
    err := DoSomething()
    if err != nil {
       span.SetError(ctx, err)
       span.SetStatusCode(ctx, {your_error_code})
    } else {
       span.SetStatusCode(ctx, 0)
    }
    
    span.SetOutput(ctx, "{your_output}")
    span.Finish(ctx)
    return err
}
```

## Prompt 拉取示例代码 {#6fcda9a1}
在使用 SDK 拉取 Prompt 前，需要在扣子罗盘的 Prompt 开发页面获取 Prompt Key 和版本号。
:::tip 说明
只支持获取已提交的 Prompt 配置。
:::
![Image=2826x669](https://p9-arcosite.byteimg.com/tos-cn-i-goo7wpa0wc/affe20efa44c471bb1d901e4e9bdb8af~tplv-goo7wpa0wc-image.image)
### Eino {#89cba151}
扣子罗盘 SDK 提供的 Prompt 组件，支持 Prompt 拉取能力。该组件还支持与 Eino 框架无缝集成，为 Eino 框架提供 Prompt 的统一管理和版本控制。
#### 安装 Go SDK {#c0fe6e6e}
```Go
go get github.com/cloudwego/eino-ext/components/prompt/cozeloop
```

#### 示例代码 {#aed29f2e}
以下示例代码展示了如何通过扣子罗盘 Go SDK 使用 PromptHub 能力。 

1. 通过环境变量的方式完成授权。具体说明，请参考[SDK 鉴权](/cozeloop/authentication-for-sdk)。
2. 初始化扣子罗盘客户端。
3. 创建 PromptHub 组件。
4. 通过直接调用方式和 Graph 编排方式来使用 PromptHub 组件格式化提示词。

```Go
package main

import (
        "context"
        "log"

        "github.com/cloudwego/eino-ext/components/prompt/cozeloop"
        "github.com/cloudwego/eino/compose"
        "github.com/cloudwego/eino/schema"
        cozeloopgo "github.com/coze-dev/cozeloop-go"
)

func main() {
        // Set the following environment variables first:
        // COZELOOP_WORKSPACE_ID=your workspace id
        // COZELOOP_API_TOKEN=your token (for testing)
        // Or use JWT OAuth with:
        // COZELOOP_JWT_OAUTH_CLIENT_ID=your client id
        // COZELOOP_JWT_OAUTH_PRIVATE_KEY=your private key
        // COZELOOP_JWT_OAUTH_PUBLIC_KEY_ID=your public key id

        ctx := context.Background()

        // Initialize CozeLoop client
        client, err := cozeloopgo.NewClient()
        if err != nil {
                log.Fatalf("Failed to create CozeLoop client: %v", err)
        }
        defer client.Close(ctx)

        // Create PromptHub component
        ph, err := cozeloop.NewPromptHub(ctx, &cozeloop.Config{
                Key:            "your.prompt.key", // Replace with your prompt key
                Version:        "",                // Empty for latest version, or specify like "1.0.0"
                CozeLoopClient: client,
        })
        if err != nil {
                log.Fatalf("Failed to create PromptHub: %v", err)
        }

        // Example 1: Direct usage - Format the prompt with variables
        log.Println("=== Example 1: Direct Format ===")
        input := map[string]any{
                "input": "What is the weather like today?",
                // Add other variables your prompt template requires
                // For example:
                // "user_name": "Alice",
                // "context": "some context",
        }

        messages, err := ph.Format(ctx, input)
        if err != nil {
                log.Fatalf("Failed to format prompt: %v", err)
        }

        log.Printf("Formatted prompt messages: %+v\n", messages)

        // Example 2: Using with Graph
        log.Println("\n=== Example 2: Using with Graph ===")
        g := compose.NewGraph[map[string]any, []*schema.Message]()
        err = g.AddChatTemplateNode("your_node_key", ph)
        if err != nil {
                log.Fatalf("Failed to add PromptHub node: %v", err)
        }

        // Add edges to connect the node from START to END
        err = g.AddEdge(compose.START, "your_node_key")
        if err != nil {
                log.Fatalf("Failed to add edge from START: %v", err)
        }
        err = g.AddEdge("your_node_key", compose.END)
        if err != nil {
                log.Fatalf("Failed to add edge to END: %v", err)
        }

        // Compile the graph
        runnable, err := g.Compile(ctx)
        if err != nil {
                log.Fatalf("Failed to compile graph: %v", err)
        }

        // Run the graph with the same input
        output, err := runnable.Invoke(ctx, input)
        if err != nil {
                log.Fatalf("Failed to run graph: %v", err)
        }

        // Print the result
        log.Printf("Graph output: %+v\n", output)
}
```

### Low-Level API {#2d310aa1}
扣子罗盘 SDK 提供接口来拉取在扣子罗盘中创建并提交的 Prompt。通过 `GetPrompt` 方法可以获取指定 Key 的 Prompt（支持指定版本），然后使用 `PromptFormat` 方法完成变量替换。启用 PromptTrace 功能后，SDK 会自动记录 Prompt 的获取和渲染过程，便于后续分析和优化。
以下是 Prompt 上报的示例代码。
```Go
import (
    "context"

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

var (
    // 初始化client，打开prompt trace上报开关
    client, _ = cozeloop.NewClient(cozeloop.WithPromptTrace(true))
)

func GetPrompt(ctx context.Context, params map[string]any) ([]*entity.Message, error) {
    // 当version不为空时，将拉取特定版本的prompt
    // 当version为空时，将拉取最新版本的prompt
    prompt, _ := client.GetPrompt(ctx, cozeloop.GetPromptParam{PromptKey: {promptKey}, Version: {version}})  
    // 完成prompt中的变量替换
    return client.PromptFormat(ctx, prompt, params)
}
```

## 更多示例 {#30764511}
扣子罗盘 Go SDK 提供多种授权方式、常见使用方式的示例代码，便于开发者直接参考使用。 更多示例，访问 [Github](https://github.com/coze-dev/cozeloop-go/tree/main/examples)。
<!-- @cols-width: 121,279,462 -->
| | | | \
|**模块** |**示例文件** |**说明** |
|---|---|---|
| | | | \
|授权  |[pat.go](https://github.com/coze-dev/cozeloop-go/blob/main/examples/init/pat/pat.go) |通过个人访问密钥实现授权。  |
|^^| | | \
| |[oauth_jwt.go](https://github.com/coze-dev/cozeloop-go/blob/main/examples/init/oauth_jwt/oauth_jwt.go) |通过 OAuth JWT 方式实现授权。  |
| | | | \
|Prompt |[prompt_hub.go](https://github.com/coze-dev/cozeloop-go/blob/main/examples/prompt/prompt_hub.go) |拉取扣子罗盘空间内的 Prompt，并进行变量替换。 |
|^^| | | \
| |[prompt_hub_jinja.go](https://github.com/coze-dev/cozeloop-go/blob/main/examples/prompt/advance/prompt_hub_jinja.go) |拉取扣子罗盘空间内的使用 Jinja2 模版的 Prompt，并进行变量替换。 |
|^^| | | \
| |[prompt_hub_multipart.go](https://github.com/coze-dev/cozeloop-go/blob/main/examples/prompt/prompt_hub_multipart/prompt_hub_multipart.go) |拉取扣子罗盘空间内的 Prompt，并注入多模态变量。 |
| | | | \
|Trace |[simple.go](https://github.com/coze-dev/cozeloop-go/blob/main/examples/trace/simple/simple.go) |实现最基本的 Trace 数据上报。 |
|^^| | | \
| |[parent_child.go](https://github.com/coze-dev/cozeloop-go/blob/main/examples/trace/parent_child/parent_child.go) |正确设置 span 的父子关系。 |
|^^| | | \
| |[large_text.go](https://github.com/coze-dev/cozeloop-go/blob/main/examples/trace/large_text/large_text.go) |实现超大文本上报。 |
|^^| | | \
| |[multi_modality.go](https://github.com/coze-dev/cozeloop-go/blob/main/examples/trace/multi_modality/multi_modality.go) |实现多模态数据上报。 |
|^^| | | \
| |[transfer_between_services.go](https://github.com/coze-dev/cozeloop-go/blob/main/examples/trace/transfer_between_services/transfer_between_services.go) |实现跨进程 Trace 数据串联。 |
| | | | \
|异常处理  |[error.go](https://github.com/coze-dev/cozeloop-go/blob/main/examples/init/error/error.go) |处理 SDK 异常。  |
| | | | \
|获取日志  |[log.go](https://github.com/coze-dev/cozeloop-go/blob/main/examples/init/log/log.go) |修改 SDK 内部打印日志的级别。 |


