feat(agent): implement dynamically hot-swappable agent interceptor

This commit is contained in:
Tim Z. 2026-04-07 11:56:06 +02:00
parent 0400b31c8e
commit 318884ff51

View file

@ -58,6 +58,7 @@ type AgentLoop struct {
hookRuntime hookRuntime hookRuntime hookRuntime
steering *steeringQueue steering *steeringQueue
pendingSkills sync.Map pendingSkills sync.Map
agentOverrides sync.Map // map[string]string (key: SessionKey, value: AgentID)
mu sync.RWMutex mu sync.RWMutex
// Concurrent turn management (from HEAD) // Concurrent turn management (from HEAD)
@ -1371,6 +1372,29 @@ func (al *AgentLoop) processMessage(ctx context.Context, msg bus.InboundMessage)
return al.processSystemMessage(ctx, msg) return al.processSystemMessage(ctx, msg)
} }
content := strings.TrimSpace(msg.Content)
if strings.HasPrefix(content, "/agent ") {
newAgentName := strings.TrimSpace(strings.TrimPrefix(content, "/agent "))
if _, ok := al.GetRegistry().GetAgent(newAgentName); ok {
route, _, err := al.resolveMessageRoute(msg)
if err == nil {
sessionKey := resolveScopeKey(route, msg.SessionKey)
al.agentOverrides.Store(sessionKey, newAgentName)
respMsg := "Switched active agent to: " + newAgentName
if al.channelManager != nil {
al.channelManager.SendPlaceholder(ctx, msg.Channel, msg.ChatID)
}
al.PublishResponseIfNeeded(ctx, msg.Channel, msg.ChatID, respMsg)
return respMsg, nil
}
} else {
respMsg := fmt.Sprintf("Agent '%s' not found in active config.", newAgentName)
al.PublishResponseIfNeeded(ctx, msg.Channel, msg.ChatID, respMsg)
return respMsg, nil
}
}
route, agent, routeErr := al.resolveMessageRoute(msg) route, agent, routeErr := al.resolveMessageRoute(msg)
if routeErr != nil { if routeErr != nil {
return "", routeErr return "", routeErr
@ -1387,6 +1411,17 @@ func (al *AgentLoop) processMessage(ctx context.Context, msg bus.InboundMessage)
scopeKey := resolveScopeKey(route, msg.SessionKey) scopeKey := resolveScopeKey(route, msg.SessionKey)
sessionKey := scopeKey sessionKey := scopeKey
// Hot-Swap Override Integration
if overrideRaw, ok := al.agentOverrides.Load(sessionKey); ok {
if overrideAgent, exists := al.GetRegistry().GetAgent(overrideRaw.(string)); exists {
agent = overrideAgent
logger.InfoCF("agent", "Applied agent override via hot-swap", map[string]any{
"session_key": sessionKey,
"overridden_agent": overrideRaw.(string),
})
}
}
logger.InfoCF("agent", "Routed message", logger.InfoCF("agent", "Routed message",
map[string]any{ map[string]any{
"agent_id": agent.ID, "agent_id": agent.ID,