可观测与调试

AgentScope Java 提供了多种机制来观测和调试智能体的执行过程:

  • Studio(可视化调试):通过 Web 界面实时可视化和交互式调试

  • OpenTelemetry 链路追踪:通过 OTLP 协议将 Trace 数据导出到外部可观测性平台(如 Langfuse、Jaeger)


Studio(可视化调试)

Studio 提供 Web 界面实时可视化 Agent 执行过程,支持交互式调试和消息追踪。


核心特性

  • 实时可视化:Web 界面展示 Agent 推理和执行过程

  • 交互式输入:通过 Web UI 与 Agent 对话

  • 消息追踪:查看完整的消息流和Trace

  • 多 Run 管理:支持多个实验运行的组织和比较


快速开始

1. 启动 Studio Server

从源码启动

git clone https://github.com/agentscope-ai/agentscope-studio
cd agentscope-studio
npm install
npm run dev

npm安装

npm install -g @agentscope/studio  # or npm install @agentscope/studio
as_studio

Studio 将运行在 http://localhost:5173(前端开发服务器) Studio Server 页面

2. Java 应用集成

import io.agentscope.core.studio.StudioManager;
import io.agentscope.core.studio.StudioMessageHook;
import io.agentscope.core.studio.StudioUserAgent;

// 初始化 Studio 连接
StudioManager.init()
    .studioUrl("http://localhost:3000")
    .project("MyProject")
    .runName("demo_" + System.currentTimeMillis())
    .initialize()
    .block();

// 创建带 Hook 的 Agent
ReActAgent agent = ReActAgent.builder()
    .name("Assistant")
    .model(model)
    .hook(new StudioMessageHook(StudioManager.getClient()))
    .build();

// Agent 消息自动发送到 Studio
agent.call(msg).block();

// 清理资源
StudioManager.shutdown();

3. 在AgentScope Studio 查看Trace信息

Trace信息

StudioUserAgent

通过 Web UI 接收用户输入。

import io.agentscope.core.studio.StudioUserAgent;

// 创建用户 Agent
StudioUserAgent user = StudioUserAgent.builder()
    .name("User")
    .studioClient(StudioManager.getClient())
    .webSocketClient(StudioManager.getWebSocketClient())
    .build();

// 等待 Web UI 用户输入
Msg userInput = user.call(null).block();

您可以在Studio中的Projects中找到该Project,通过WebUI的方式进行调试 Studio Server Web UI 输入界面

对话循环

Msg msg = null;
while (true) {
    // 从 Web UI 获取用户输入
    msg = user.call(msg).block();

    if (msg == null || "exit".equalsIgnoreCase(msg.getTextContent())) {
        break;
    }

    // Agent 处理
    msg = agent.call(msg).block();
}

完整示例

package io.agentscope.examples;

import io.agentscope.core.ReActAgent;
import io.agentscope.core.message.Msg;
import io.agentscope.core.model.DashScopeChatModel;
import io.agentscope.core.studio.StudioManager;
import io.agentscope.core.studio.StudioMessageHook;
import io.agentscope.core.studio.StudioUserAgent;

public class StudioExample {

    public static void main(String[] args) throws Exception {
        String apiKey = System.getenv("DASHSCOPE_API_KEY");

        System.out.println("Connecting to Studio at http://localhost:3000...");

        // 初始化 Studio
        StudioManager.init()
            .studioUrl("http://localhost:3000")
            .project("JavaExamples")
            .runName("studio_demo_" + System.currentTimeMillis())
            .initialize()
            .block();
        System.out.println("Connected to Studio\n");

        try {
            // 创建 Agent(带 Studio Hook)
            ReActAgent agent = ReActAgent.builder()
                .name("Assistant")
                .sysPrompt("You are a helpful AI assistant.")
                .model(DashScopeChatModel.builder()
                    .apiKey(apiKey)
                    .modelName("qwen3-max")
                    .build())
                .hook(new StudioMessageHook(StudioManager.getClient()))
                .build();

            // 创建用户 Agent
            StudioUserAgent user = StudioUserAgent.builder()
                .name("User")
                .studioClient(StudioManager.getClient())
                .webSocketClient(StudioManager.getWebSocketClient())
                .build();

            // 对话循环
            System.out.println("Starting conversation (type 'exit' to quit)");
            System.out.println("Open http://localhost:3000 to interact\n");

            Msg msg = null;
            int turn = 1;
            while (true) {
                System.out.println("[Turn " + turn + "] Waiting for user input...");
                msg = user.call(msg).block();

                if (msg == null || "exit".equalsIgnoreCase(msg.getTextContent())) {
                    System.out.println("\nConversation ended");
                    break;
                }

                System.out.println("[Turn " + turn + "] User: " + msg.getTextContent());
                msg = agent.call(msg).block();

                if (msg != null) {
                    System.out.println("[Turn " + turn + "] Agent: "
                        + msg.getTextContent() + "\n");
                }
                turn++;
            }

        } finally {
            System.out.println("\nShutting down...");
            StudioManager.shutdown();
            System.out.println("Done\n");
        }
    }
}

高级用法

手动推送消息

StudioClient client = StudioManager.getClient();

Msg customMsg = Msg.builder()
    .role(MsgRole.ASSISTANT)
    .content(TextBlock.builder().text("自定义消息").build())
    .build();

client.pushMessage(customMsg).block();

多 Agent 可视化

// 为每个 Agent 添加 Hook
ReActAgent agent1 = ReActAgent.builder()
    .name("Agent1")
    .hook(new StudioMessageHook(client))
    .build();

ReActAgent agent2 = ReActAgent.builder()
    .name("Agent2")
    .hook(new StudioMessageHook(client))
    .build();

// Studio 将分别显示两个 Agent 的消息

OpenTelemetry 链路追踪

AgentScope Java 集成了 OpenTelemetry,提供分布式链路追踪能力。你可以将 Trace 导出到任何支持 OTLP 协议的平台,如 Langfuse。

快速开始

使用 TelemetryTracer 并通过 TracerRegistry 注册,即可自动追踪所有智能体调用、模型调用和工具执行:

import io.agentscope.core.tracing.TracerRegistry;
import io.agentscope.core.tracing.telemetry.TelemetryTracer;

// 注册 TelemetryTracer,配置 OTLP 端点
TracerRegistry.register(
    TelemetryTracer.builder()
        .endpoint("https://your-otlp-endpoint/v1/traces")
        .build()
);

// 注册后,所有智能体活动将自动被追踪
ReActAgent agent = ReActAgent.builder()
    .name("Assistant")
    .model(model)
    .build();

注册后,追踪器会自动捕获:

  • 智能体调用 — 每次 agent.call() 生成一个 Span

  • 模型调用 — 每次 LLM 调用生成一个 Span

  • 工具执行 — 每次工具调用生成一个 Span

  • 格式化 — 消息格式化生成一个 Span

无需额外代码 — 追踪在全局范围内自动生效。

配置选项

TelemetryTracer 支持以下 Builder 选项:

选项

描述

默认值

endpoint

OTLP 端点 URL

addHeader

添加单个 HTTP 请求头(如用于认证)

headers

Map 形式设置所有 HTTP 请求头

enabled

启用或禁用追踪

true

tracer

使用自定义的 OpenTelemetry Tracer 实例

接入 Langfuse

Langfuse 是一个开源的可观测性平台,支持 OpenTelemetry 协议。你可以将 Trace 发送到 Langfuse Cloud 或自部署的实例。

import io.agentscope.core.tracing.TracerRegistry;
import io.agentscope.core.tracing.telemetry.TelemetryTracer;
import java.util.Base64;

// 将 Langfuse API Key 编码为 Base64
String publicKey = "pk-lf-xxxxxxxx";
String secretKey = "sk-lf-xxxxxxxx";
String encoded = Base64.getEncoder().encodeToString((publicKey + ":" + secretKey).getBytes());

TracerRegistry.register(
    TelemetryTracer.builder()
        .endpoint("https://cloud.langfuse.com/api/public/otel/v1/traces")
        .addHeader("Authorization", "Basic " + encoded)
        .addHeader("x-langfuse-ingestion-version", "4")
        .build()
);

注意:使用 Langfuse 的 OTLP 端点时,x-langfuse-ingestion-version 请求头是必需的,请确保包含此头部。

运行智能体后,你可以在 Langfuse 控制台中查看 Trace,包括完整的调用链、延迟以及每一步的输入/输出。

接入其他 OTLP 后端

任何支持 OTLP 协议的平台都可以使用。例如,将 Trace 发送到本地 Jaeger 实例:

TracerRegistry.register(
    TelemetryTracer.builder()
        .endpoint("http://localhost:4317")
        .build()
);

更多资源

  • Studio 完整示例: StudioExample.java

  • Studio 仓库: https://github.com/agentscope-ai/agentscope-studio

  • Hook 文档: hook.md