feat(agent): audio config context propagation in tool callbacks

Add audio config context helpers in pipeline callbacks. Propagate voice/model
selections through agent loop resolver for tool invocation.
This commit is contained in:
viettranx committed 2026-04-15 11:24:57 +07:00
1 parent 8d187ca074
commit a7c8170c4a
3 files changed
+29 -5

No files matched your search

@@ -35,6 +35,15 @@ func (l *Loop) makeExecuteToolCall(req *RunRequest, bridgeRS *runState) func(ctx
toolStart := time.Now().UTC()
toolSpanID := l.emitToolSpanStart(ctx, toolStart, tc.Name, tc.ID, string(argsJSON))
// Inject agent audio snapshot so TTS tool (and any future audio consumers)
// can read agent-level voice/model config without an extra DB lookup.
if l.agentUUID != uuid.Nil {
ctx = store.WithAgentAudio(ctx, store.AgentAudioSnapshot{
AgentID: l.agentUUID,
OtherConfig: append([]byte(nil), l.agentOtherConfig...), // defensive copy at dispatch
})
}
result := l.tools.ExecuteWithContext(ctx, registryName, tc.Arguments,
req.Channel, req.ChatID, req.PeerKind, req.SessionKey, nil)
toolDuration := time.Since(toolStart)
@@ -84,6 +93,14 @@ func (l *Loop) makeExecuteToolRaw(req *RunRequest) func(ctx context.Context, tc
start := time.Now().UTC()
spanID := l.emitToolSpanStart(ctx, start, tc.Name, tc.ID, string(argsJSON))
// Inject agent audio snapshot (parallel path — same as sequential makeExecuteToolCall).
if l.agentUUID != uuid.Nil {
ctx = store.WithAgentAudio(ctx, store.AgentAudioSnapshot{
AgentID: l.agentUUID,
OtherConfig: append([]byte(nil), l.agentOtherConfig...), // defensive copy at dispatch
})
}
result := l.tools.ExecuteWithContext(ctx, registryName, tc.Arguments,
req.Channel, req.ChatID, req.PeerKind, req.SessionKey, nil)
dur := time.Since(start)
+11 -5
View File
@@ -2,6 +2,7 @@ package agent
import (
"context"
"encoding/json"
"sync"
"sync/atomic"
@@ -78,8 +79,11 @@ type Loop struct {
// agentUUID is the canonical DB primary key. Use for SQL WHERE/JOIN,
// DomainEvent.AgentID, OTel span attributes, and context propagation via
// store.WithAgentID. See docs/agent-identity-conventions.md.
agentUUID uuid.UUID
tenantID uuid.UUID // agent's owning tenant
agentUUID uuid.UUID
tenantID uuid.UUID // agent's owning tenant
// agentOtherConfig is a defensive byte copy of agents.other_config JSONB.
// Copied once at Loop construction; used to build AgentAudioSnapshot at tool dispatch.
agentOtherConfig json.RawMessage
agentType string // "open" or "predefined"
defaultTimezone string // system default timezone for bootstrap pre-fill
provider providers.Provider
@@ -319,9 +323,10 @@ type LoopConfig struct {
ShellDenyGroups map[string]bool
// Agent UUID + tenant for context propagation to tools
AgentUUID uuid.UUID
TenantID uuid.UUID // agent's owning tenant — injected into execution context
AgentType string // "open" or "predefined"
AgentUUID uuid.UUID
TenantID uuid.UUID // agent's owning tenant — injected into execution context
AgentOtherConfig json.RawMessage // raw other_config JSONB — copied defensively in NewLoop
AgentType string // "open" or "predefined"
DisplayName string // human-readable agent display name (for runtime section)
IsTeamLead bool // agent leads a team (from resolver detection)
@@ -449,6 +454,7 @@ func NewLoop(cfg LoopConfig) *Loop {
displayName: cfg.DisplayName,
agentUUID: cfg.AgentUUID,
tenantID: cfg.TenantID,
agentOtherConfig: append([]byte(nil), cfg.AgentOtherConfig...), // defensive copy
agentType: cfg.AgentType,
provider: cfg.Provider,
model: cfg.Model,
+1
View File
@@ -451,6 +451,7 @@ func NewManagedResolver(deps ResolverDeps) ResolverFunc {
DisplayName: ag.DisplayName,
AgentUUID: ag.ID,
TenantID: ag.TenantID,
AgentOtherConfig: ag.OtherConfig,
AgentType: ag.AgentType,
IsTeamLead: isTeamLead,
AutoInjector: deps.AutoInjector,