监控与调试 (Monitoring & Debugging)

在生产环境中运行 Agent 系统时,"黑盒"是最大的敌人。你需要知道 Agent 正在做什么,为什么这么做,以及在出错时如何恢复。LangGraphGo 提供了多层次的监控和调试工具。

1. 监听器 (Listeners)

背景与功能

监听器允许你以非侵入式的方式订阅图的生命周期事件。你可以监控节点何时开始、何时结束、输入是什么、输出是什么,以及是否发生了错误。

这对于集成日志系统(如 Zap, Logrus)、分布式追踪(如 OpenTelemetry)或实时监控仪表盘非常有用。

实现原理

运行时在关键的执行点(节点启动前、节点结束后、发生错误时)会触发事件。注册的监听器函数会被同步或异步调用。

代码展示

// 定义监听器函数
listener := func(event graph.Event) {
    switch event.Type {
    case graph.NodeStart:
        log.Printf("[START] Node: %s, Input: %v", event.Node, event.Input)
    case graph.NodeEnd:
        log.Printf("[END] Node: %s, Output: %v", event.Node, event.Output)
    case graph.Error:
        log.Printf("[ERROR] Node: %s, Err: %v", event.Node, event.Error)
    }
}

// 注册监听器
runnable.AddListener(listener)

2. 持久化执行 (Durable Execution)

背景与功能

Agent 任务可能运行很长时间(数分钟甚至数小时)。如果进程崩溃或服务器重启,我们不希望从头开始。持久化执行允许任务从上次成功的 Checkpoint 自动恢复。

实现原理

这依赖于 Checkpointing 机制。每次状态更新都会被持久化。当系统重启并使用相同的 ThreadID 恢复时,它会首先加载最新的 Checkpoint,然后从那里继续执行。

代码展示

// 1. 获取最新状态
latestCheckpoint, err := store.GetLatest(threadID)

if latestCheckpoint != nil {
    // 2. 如果有历史,则恢复
    log.Println("Resuming from checkpoint...")
    runnable.ResumeFromCheckpoint(ctx, latestCheckpoint.ID)
} else {
    // 3. 否则重新开始
    log.Println("Starting new execution...")
    runnable.Invoke(ctx, input)
}

3. 调试工具

除了上述机制,LangGraphGo 还建议结合标准的 Go 调试工具(如 Delve)和性能分析工具(pprof)来深入分析 Agent 的行为。