feat(audit): Phase 4 - Integrate audit logging with agent loop

Add comprehensive audit logging to agent message processing:

- Generate request ID at message entry point for request tracing
- Audit log inbound messages with session correlation
- Audit log outbound responses
- Audit log LLM tool call requests
- Set agent ID in context for attribution

This provides end-to-end visibility into agent message flow:
- Request ID tracks complete conversation lifecycle
- Session ID links related messages
- Agent ID identifies which agent handled the request
This commit is contained in:
Vishnuvardhan Reddy 2026-03-01 15:27:14 +00:00
parent 19018a3107
commit 957db4be42

View file

@ -18,6 +18,7 @@ import (
"time"
"unicode/utf8"
"github.com/sipeed/picoclaw/pkg/audit"
"github.com/sipeed/picoclaw/pkg/bus"
"github.com/sipeed/picoclaw/pkg/channels"
"github.com/sipeed/picoclaw/pkg/config"
@ -341,6 +342,14 @@ func (al *AgentLoop) ProcessHeartbeat(ctx context.Context, content, channel, cha
}
func (al *AgentLoop) processMessage(ctx context.Context, msg bus.InboundMessage) (string, error) {
// Generate request ID for audit trail correlation
requestID := fmt.Sprintf("req-%d-%s", time.Now().UnixNano(), msg.SenderID)
ctx = audit.WithRequestID(ctx, requestID)
ctx = audit.WithSessionID(ctx, msg.SessionKey)
// Audit log inbound message
audit.LogMessage(ctx, "inbound", "text", msg.Content, msg.MessageID)
// Add message preview to log (show full content for error messages)
var logContent string
if strings.Contains(msg.Content, "Error:") || strings.Contains(msg.Content, "error") {
@ -534,6 +543,7 @@ func (al *AgentLoop) runAgentLoop(ctx context.Context, agent *AgentInstance, opt
// 8. Optional: send response via bus
if opts.SendResponse {
audit.LogMessage(ctx, "outbound", "text", finalContent, "")
al.bus.PublishOutbound(ctx, bus.OutboundMessage{
Channel: opts.Channel,
ChatID: opts.ChatID,
@ -825,6 +835,25 @@ func (al *AgentLoop) runLLMIteration(
"iteration": iteration,
})
// Audit log the tool call request from LLM
for _, tc := range normalizedToolCalls {
audit.Log(&audit.Entry{
Level: audit.LevelInfo,
Component: "agent",
EventType: audit.EventToolCall,
AgentID: agent.ID,
Channel: opts.Channel,
ChatID: opts.ChatID,
ToolCall: &audit.ToolCallData{
ToolID: tc.ID,
Name: tc.Name,
Arguments: tc.Arguments,
IsAsync: false,
IsError: false,
},
})
}
// Build assistant message with tool calls
assistantMsg := providers.Message{
Role: "assistant",