跟踪
本页面包含有关跟踪功能的详细信息,该功能为 AI Agent 提供了全面的跟踪能力。
功能概述
跟踪功能是一个强大的监控与调试工具,可捕获 Agent 运行的详细信息,包括:
- 策略执行
- LLM 调用
- LLM 流式传输(开始、帧、完成、错误)
- 工具调用
- Agent 图中的节点执行
该功能通过拦截 Agent 流水线中的关键事件并将其转发给可配置的消息处理器来工作。这些处理器可以将跟踪信息输出到各种目标,例如日志文件或文件系统中的其他类型文件,使开发者能够洞察 Agent 行为并有效地排除故障。
事件流
- 跟踪功能拦截 Agent 流水线中的事件。
- 根据配置的消息筛选器对事件进行过滤。
- 过滤后的事件被传递给注册的消息处理器。
- 消息处理器对事件进行格式化并输出到各自的目标。
配置与初始化
基础设置
要使用跟踪功能,您需要:
- 拥有一个或多个消息处理器(可以使用现有的或创建自己的)。
- 在 Agent 中安装
Tracing。 - 配置消息筛选器(可选)。
- 将消息处理器添加到功能中。
=== "Kotlin"
<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent
import ai.koog.agents.core.feature.model.events.LLMCallCompletedEvent
import ai.koog.agents.core.feature.model.events.ToolCallStartingEvent
import ai.koog.agents.features.tracing.feature.Tracing
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageFileWriter;
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageLogWriter
import ai.koog.prompt.executor.llms.all.simpleOllamaAIExecutor
import ai.koog.prompt.executor.ollama.client.OllamaModels
import io.github.oshai.kotlinlogging.KotlinLogging
import kotlinx.io.buffered
import kotlinx.io.files.Path
import kotlinx.io.files.SystemFileSystem
-->
```kotlin
// 定义将用作跟踪消息目标的 logger/文件
val logger = KotlinLogging.logger { }
val outputPath = Path("/path/to/trace.log")
// 创建 Agent
val agent = AIAgent(
promptExecutor = simpleOllamaAIExecutor(),
llmModel = OllamaModels.Meta.LLAMA_3_2,
) {
install(Tracing) {
// 配置消息处理器以处理跟踪事件
addMessageProcessor(TraceFeatureMessageLogWriter(logger))
addMessageProcessor(TraceFeatureMessageFileWriter.create(outputPath))
}
}
```
<!--- KNIT example-tracing-01.kt -->
=== "Java"
<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent;
import ai.koog.agents.features.tracing.feature.Tracing;
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageFileWriter;
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageLogWriter;
import ai.koog.prompt.executor.model.PromptExecutor;
import ai.koog.prompt.executor.ollama.client.OllamaModels;
import org.slf4j.LoggerFactory;
import java.nio.file.Path;
public class exampleTracingJava01 {
public static void main(String[] args) {
-->
<!--- SUFFIX
}
}
-->
```java
// 定义将用作跟踪消息目标的 logger/文件
var logger = LoggerFactory.getLogger("tracing");
var outputPath = Path.of("/path/to/trace.log");
// 创建 Agent
var agent = AIAgent.builder()
.promptExecutor(PromptExecutor.builder().ollama().build())
.llmModel(OllamaModels.Meta.LLAMA_3_2)
.install(Tracing.Feature, config -> {
// 配置消息处理器以处理跟踪事件
config.addMessageProcessor(TraceFeatureMessageLogWriter.create(logger));
config.addMessageProcessor(TraceFeatureMessageFileWriter.create(outputPath));
})
.build();
```
<!--- KNIT exampleTracingJava01.java -->
消息过滤
您可以处理所有现有事件,也可以根据特定条件选择其中的一部分。 消息筛选器让您可以控制处理哪些事件。这对于关注 Agent 运行的特定方面非常有用:
=== "Kotlin"
<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent
import ai.koog.agents.core.feature.model.events.*
import ai.koog.agents.example.exampleTracing01.outputPath
import ai.koog.agents.features.tracing.feature.Tracing
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageFileWriter
import ai.koog.prompt.executor.llms.all.simpleOllamaAIExecutor
import ai.koog.prompt.executor.ollama.client.OllamaModels
import kotlinx.io.buffered
import kotlinx.io.files.Path
import kotlinx.io.files.SystemFileSystem
val agent = AIAgent(
promptExecutor = simpleOllamaAIExecutor(),
llmModel = OllamaModels.Meta.LLAMA_3_2,
) {
install(Tracing) {
-->
<!--- SUFFIX
}
}
-->
```kotlin
val fileWriter = TraceFeatureMessageFileWriter(
outputPath,
{ path: Path -> SystemFileSystem.sink(path).buffered() }
)
addMessageProcessor(fileWriter)
// 仅过滤与 LLM 相关的事件
fileWriter.setMessageFilter { message ->
message is LLMCallStartingEvent || message is LLMCallCompletedEvent
}
// 仅过滤与工具相关的事件
fileWriter.setMessageFilter { message ->
message is ToolCallStartingEvent ||
message is ToolCallCompletedEvent ||
message is ToolValidationFailedEvent ||
message is ToolCallFailedEvent
}
// 仅过滤节点执行相关的事件
fileWriter.setMessageFilter { message ->
message is NodeExecutionStartingEvent || message is NodeExecutionCompletedEvent
}
```
<!--- KNIT example-tracing-02.kt -->
=== "Java"
<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent;
import ai.koog.agents.core.feature.model.events.*;
import ai.koog.agents.features.tracing.feature.Tracing;
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageFileWriter;
import ai.koog.prompt.executor.model.PromptExecutor;
import ai.koog.prompt.executor.ollama.client.OllamaModels;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class exampleTracingJava02 {
public static void main(String[] args) {
var outputPath = Path.of("/path/to/trace.log");
var agent = AIAgent.builder()
.promptExecutor(PromptExecutor.builder().ollama().build())
.llmModel(OllamaModels.Meta.LLAMA_3_2)
.install(Tracing.Feature, config -> {
-->
<!--- SUFFIX
})
.build();
}
}
-->
```java
var fileWriter = TraceFeatureMessageFileWriter.create(
outputPath,
path -> { try { return Files.newOutputStream(path); } catch (IOException e) { throw new UncheckedIOException(e); }}
);
config.addMessageProcessor(fileWriter);
// 仅过滤与 LLM 相关的事件
fileWriter.setMessageFilter(message ->
message instanceof LLMCallStartingEvent || message instanceof LLMCallCompletedEvent
);
// 仅过滤与工具相关的事件
fileWriter.setMessageFilter(message ->
message instanceof ToolCallStartingEvent ||
message instanceof ToolCallCompletedEvent ||
message instanceof ToolValidationFailedEvent ||
message instanceof ToolCallFailedEvent
);
// 仅过滤节点执行相关的事件
fileWriter.setMessageFilter(message ->
message instanceof NodeExecutionStartingEvent || message instanceof NodeExecutionCompletedEvent
);
```
<!--- KNIT exampleTracingJava02.java -->
大容量跟踪
对于具有复杂策略或长期运行执行任务的 Agent,跟踪事件的数量可能会非常庞大。请考虑使用以下方法来管理事件量:
- 使用特定的消息筛选器来减少事件数量。
- 实现带缓冲或采样的自定义消息处理器。
- 对日志文件使用文件轮转,防止其增长过大。
依赖图
跟踪功能具有以下依赖关系:
Tracing
├── AIAgentPipeline (用于拦截事件)
├── TraceFeatureConfig
│ └── FeatureConfig
├── Message Processors
│ ├── TraceFeatureMessageLogWriter
│ │ └── FeatureMessageLogWriter
│ ├── TraceFeatureMessageFileWriter
│ │ └── FeatureMessageFileWriter
│ └── TraceFeatureMessageRemoteWriter
│ └── FeatureMessageRemoteWriter
└── Event Types (来自 ai.koog.agents.core.feature.model)
├── AgentStartingEvent
├── AgentCompletedEvent
├── AgentExecutionFailedEvent
├── AgentClosingEvent
├── GraphStrategyStartingEvent
├── FunctionalStrategyStartingEvent
├── StrategyCompletedEvent
├── NodeExecutionStartingEvent
├── NodeExecutionCompletedEvent
├── NodeExecutionFailedEvent
├── SubgraphExecutionStartingEvent
├── SubgraphExecutionCompletedEvent
├── SubgraphExecutionFailedEvent
├── LLMCallStartingEvent
├── LLMCallCompletedEvent
├── LLMStreamingStartingEvent
├── LLMStreamingFrameReceivedEvent
├── LLMStreamingFailedEvent
├── LLMStreamingCompletedEvent
├── ToolCallStartingEvent
├── ToolValidationFailedEvent
├── ToolCallFailedEvent
└── ToolCallCompletedEvent示例与快速入门
基础 logger 跟踪
=== "Kotlin"
<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent
import ai.koog.agents.features.tracing.feature.Tracing
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageLogWriter
import ai.koog.prompt.executor.llms.all.simpleOllamaAIExecutor
import ai.koog.prompt.executor.ollama.client.OllamaModels
import io.github.oshai.kotlinlogging.KotlinLogging
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
-->
<!--- SUFFIX
}
-->
```kotlin
// 创建 logger
val logger = KotlinLogging.logger { }
// 创建带有跟踪功能的 Agent
val agent = AIAgent(
promptExecutor = simpleOllamaAIExecutor(),
llmModel = OllamaModels.Meta.LLAMA_3_2,
) {
install(Tracing) {
addMessageProcessor(TraceFeatureMessageLogWriter(logger))
}
}
// 运行 Agent
agent.run("Hello, agent!")
```
<!--- KNIT example-tracing-03.kt -->
=== "Java"
<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent;
import ai.koog.agents.features.tracing.feature.Tracing;
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageLogWriter;
import ai.koog.prompt.executor.model.PromptExecutor;
import ai.koog.prompt.executor.ollama.client.OllamaModels;
import org.slf4j.LoggerFactory;
public class exampleTracingJava03 {
public static void main(String[] args) {
-->
<!--- SUFFIX
}
}
-->
```java
// 创建 logger
var logger = LoggerFactory.getLogger("tracing");
// 创建带有跟踪功能的 Agent
var agent = AIAgent.builder()
.promptExecutor(PromptExecutor.builder().ollama().build())
.llmModel(OllamaModels.Meta.LLAMA_3_2)
.install(Tracing.Feature, config -> {
config.addMessageProcessor(TraceFeatureMessageLogWriter.create(logger));
})
.build();
// 运行 Agent
agent.run("Hello, agent!");
```
<!--- KNIT exampleTracingJava03.java -->
错误处理与极端情况
无消息处理器
如果没有将任何消息处理器添加到跟踪功能中,系统将记录一条警告:
Tracing Feature. No feature out stream providers are defined. Trace streaming has no target.该功能仍将拦截事件,但它们将不会被处理或输出到任何地方。
资源管理
消息处理器可能会持有需要正确释放的资源(如文件句柄)。使用 use 扩展函数以确保正确的清理:
=== "Kotlin"
<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent
import ai.koog.agents.example.exampleTracing01.outputPath
import ai.koog.agents.features.tracing.feature.Tracing
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageFileWriter
import ai.koog.prompt.executor.llms.all.simpleOllamaAIExecutor
import ai.koog.prompt.executor.ollama.client.OllamaModels
import kotlinx.coroutines.runBlocking
import kotlinx.io.buffered
import kotlinx.io.files.Path
import kotlinx.io.files.SystemFileSystem
const val input = "What's the weather like in New York?"
fun main() {
runBlocking {
-->
<!--- SUFFIX
}
}
-->
```kotlin
val writer = TraceFeatureMessageFileWriter(
outputPath,
{ path: Path -> SystemFileSystem.sink(path).buffered() }
)
// 创建 Agent
val agent = AIAgent(
promptExecutor = simpleOllamaAIExecutor(),
llmModel = OllamaModels.Meta.LLAMA_3_2,
) {
install(Tracing) {
addMessageProcessor(writer)
}
}
// 运行 Agent
agent.run(input)
// 块退出时 writer 将自动关闭
```
<!--- KNIT example-tracing-04.kt -->
=== "Java"
<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent;
import ai.koog.agents.features.tracing.feature.Tracing;
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageFileWriter;
import ai.koog.prompt.executor.model.PromptExecutor;
import ai.koog.prompt.executor.ollama.client.OllamaModels;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class exampleTracingJava04 {
public static void main(String[] args) {
var outputPath = Path.of("/path/to/trace.log");
String input = "What's the weather like in New York?";
-->
<!--- SUFFIX
}
}
-->
```java
var writer = TraceFeatureMessageFileWriter.create(
outputPath,
path -> { try { return Files.newOutputStream(path); } catch (IOException e) { throw new UncheckedIOException(e); }}
);
// 创建 Agent
var agent = AIAgent.builder()
.promptExecutor(PromptExecutor.builder().ollama().build())
.llmModel(OllamaModels.Meta.LLAMA_3_2)
.install(Tracing.Feature, config -> {
config.addMessageProcessor(writer);
})
.build();
// 运行 Agent
agent.run(input);
// 块退出时 writer 将自动关闭
```
<!--- KNIT exampleTracingJava04.java -->
将特定事件跟踪到文件
=== "Kotlin"
<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent
import ai.koog.agents.core.feature.model.events.LLMCallCompletedEvent
import ai.koog.agents.core.feature.model.events.LLMCallStartingEvent
import ai.koog.agents.example.exampleTracing01.outputPath
import ai.koog.agents.features.tracing.feature.Tracing
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageFileWriter
import ai.koog.prompt.executor.llms.all.simpleOllamaAIExecutor
import ai.koog.prompt.executor.ollama.client.OllamaModels
import kotlinx.coroutines.runBlocking
import kotlinx.io.buffered
import kotlinx.io.files.Path
import kotlinx.io.files.SystemFileSystem
const val input = "What's the weather like in New York?"
fun main() {
runBlocking {
-->
<!--- SUFFIX
}
}
-->
```kotlin
val fileWriter = TraceFeatureMessageFileWriter(
outputPath,
{ path: Path -> SystemFileSystem.sink(path).buffered() }
)
// 创建 Agent
val agent = AIAgent(
promptExecutor = simpleOllamaAIExecutor(),
llmModel = OllamaModels.Meta.LLAMA_3_2,
) {
install(Tracing) {
addMessageProcessor(fileWriter)
// 仅跟踪 LLM 调用
fileWriter.setMessageFilter { message ->
message is LLMCallStartingEvent || message is LLMCallCompletedEvent
}
}
}
```
<!--- KNIT example-tracing-05.kt -->
=== "Java"
<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent;
import ai.koog.agents.core.feature.model.events.LLMCallCompletedEvent;
import ai.koog.agents.core.feature.model.events.LLMCallStartingEvent;
import ai.koog.agents.features.tracing.feature.Tracing;
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageFileWriter;
import ai.koog.prompt.executor.model.PromptExecutor;
import ai.koog.prompt.executor.ollama.client.OllamaModels;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class exampleTracingJava05 {
public static void main(String[] args) {
var outputPath = Path.of("/path/to/trace.log");
String input = "What's the weather like in New York?";
-->
<!--- SUFFIX
}
}
-->
```java
var fileWriter = TraceFeatureMessageFileWriter.create(
outputPath,
path -> { try { return Files.newOutputStream(path); } catch (IOException e) { throw new UncheckedIOException(e); }}
);
// 创建 Agent
var agent = AIAgent.builder()
.promptExecutor(PromptExecutor.builder().ollama().build())
.llmModel(OllamaModels.Meta.LLAMA_3_2)
.install(Tracing.Feature, config -> {
config.addMessageProcessor(fileWriter);
// 仅跟踪 LLM 调用
fileWriter.setMessageFilter(message ->
message instanceof LLMCallStartingEvent || message instanceof LLMCallCompletedEvent
);
})
.build();
```
<!--- KNIT exampleTracingJava05.java -->
将特定事件跟踪到远程端点
当您需要通过网络发送事件数据时,可以使用远程端点跟踪。一旦启动,远程端点跟踪将在指定的端口号上启动一个轻量化服务器,并通过 Kotlin Server-Sent Events (SSE) 发送事件。
=== "Kotlin"
<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent
import ai.koog.agents.core.feature.remote.server.config.DefaultServerConnectionConfig
import ai.koog.agents.features.tracing.feature.Tracing
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageRemoteWriter
import ai.koog.prompt.executor.llms.all.simpleOllamaAIExecutor
import ai.koog.prompt.executor.ollama.client.OllamaModels
import kotlinx.coroutines.runBlocking
const val input = "What's the weather like in New York?"
const val port = 4991
const val host = "localhost"
fun main() {
runBlocking {
-->
<!--- SUFFIX
}
}
-->
```kotlin
val connectionConfig = DefaultServerConnectionConfig(host = host, port = port)
val writer = TraceFeatureMessageRemoteWriter(connectionConfig)
// 创建 Agent
val agent = AIAgent(
promptExecutor = simpleOllamaAIExecutor(),
llmModel = OllamaModels.Meta.LLAMA_3_2,
) {
install(Tracing) {
addMessageProcessor(writer)
}
}
// 运行 Agent
agent.run(input)
// 块退出时 writer 将自动关闭
```
<!--- KNIT example-tracing-06.kt -->
=== "Java"
<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent;
import ai.koog.agents.core.feature.remote.server.config.DefaultServerConnectionConfig;
import ai.koog.agents.features.tracing.feature.Tracing;
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageRemoteWriter;
import ai.koog.prompt.executor.model.PromptExecutor;
import ai.koog.prompt.executor.ollama.client.OllamaModels;
import java.io.IOException;
import java.io.UncheckedIOException;
public class exampleTracingJava06 {
public static void main(String[] args) {
String input = "What's the weather like in New York?";
int port = 4991;
String host = "localhost";
-->
<!--- SUFFIX
}
}
-->
```java
var connectionConfig = new DefaultServerConnectionConfig(host, port);
var writer = new TraceFeatureMessageRemoteWriter(connectionConfig);
// 创建 Agent
var agent = AIAgent.builder()
.promptExecutor(PromptExecutor.builder().ollama().build())
.llmModel(OllamaModels.Meta.LLAMA_3_2)
.install(Tracing.Feature, config -> {
config.addMessageProcessor(writer);
})
.build();
// 运行 Agent
agent.run(input);
// 块退出时 writer 将自动关闭
```
<!--- KNIT exampleTracingJava06.java -->
在客户端,您可以使用 FeatureMessageRemoteClient 来接收事件并对其进行反序列化。
=== "Kotlin"
<!--- INCLUDE
import ai.koog.agents.core.feature.model.events.AgentCompletedEvent
import ai.koog.agents.core.feature.model.events.DefinedFeatureEvent
import ai.koog.agents.core.feature.remote.client.config.DefaultClientConnectionConfig
import ai.koog.agents.core.feature.remote.client.FeatureMessageRemoteClient
import ai.koog.utils.io.use
import io.ktor.http.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.consumeAsFlow
const val input = "What's the weather like in New York?"
const val port = 4991
const val host = "localhost"
fun main() {
runBlocking {
-->
<!--- SUFFIX
}
}
-->
```kotlin
val clientConfig = DefaultClientConnectionConfig(host = host, port = port, protocol = URLProtocol.HTTP)
val agentEvents = mutableListOf<DefinedFeatureEvent>()
val clientJob = launch {
FeatureMessageRemoteClient(connectionConfig = clientConfig, scope = this).use { client ->
val collectEventsJob = launch {
client.receivedMessages.consumeAsFlow().collect { event ->
// 从服务器收集事件
agentEvents.add(event as DefinedFeatureEvent)
// 在 Agent 完成时停止收集事件
if (event is AgentCompletedEvent) {
cancel()
}
}
}
client.connect()
collectEventsJob.join()
client.healthCheck()
}
}
listOf(clientJob).joinAll()
```
<!--- KNIT example-tracing-07.kt -->
API 文档
跟踪功能遵循模块化架构,包含以下核心组件:
- Tracing:在 Agent 流水线中拦截事件的主功能类。
- TraceFeatureConfig:用于自定义功能行为的配置类。
- 消息处理器:处理并输出跟踪事件的组件:
- TraceFeatureMessageLogWriter:将跟踪事件写入 logger。
- TraceFeatureMessageFileWriter:将跟踪事件写入文件。
- TraceFeatureMessageRemoteWriter:将跟踪事件发送到远程服务器。
