MCPcopy Index your code
hub / github.com/docker/docker-agent / recordAssistantMessage

Method recordAssistantMessage

pkg/runtime/loop.go:999–1078  ·  view source on GitHub ↗

recordAssistantMessage adds the model's response to the session and returns per-message usage information for the token-usage event. Empty responses (no text and no tool calls) are silently skipped since providers reject them. cost is the precomputed per-turn cost (see computeMessageCost); nil recor

(
	sess *session.Session,
	a *agent.Agent,
	res streamResult,
	agentTools []tools.Tool,
	modelID string,
	cost *float64,
	events EventSink,
)

Source from the content-addressed store, hash-verified

997// cost is the precomputed per-turn cost (see computeMessageCost); nil records
998// as 0, matching the previous "no pricing data" behaviour.
999func (r *LocalRuntime) recordAssistantMessage(
1000 sess *session.Session,
1001 a *agent.Agent,
1002 res streamResult,
1003 agentTools []tools.Tool,
1004 modelID string,
1005 cost *float64,
1006 events EventSink,
1007) *MessageUsage {
1008 if strings.TrimSpace(res.Content) == "" && len(res.Calls) == 0 {
1009 slog.Debug("Skipping empty assistant message (no content and no tool calls)", "agent", a.Name())
1010 return nil
1011 }
1012
1013 // Resolve tool definitions for the tool calls.
1014 var toolDefs []tools.Tool
1015 if len(res.Calls) > 0 {
1016 toolMap := make(map[string]tools.Tool, len(agentTools))
1017 for _, t := range agentTools {
1018 toolMap[t.Name] = t
1019 }
1020 for _, call := range res.Calls {
1021 if def, ok := toolMap[call.Function.Name]; ok {
1022 toolDefs = append(toolDefs, def)
1023 }
1024 }
1025 }
1026
1027 // The per-turn cost was computed once in runTurn and threaded in;
1028 // nil means the response could not be priced and records as 0,
1029 // preserving the previous "no pricing data" behaviour. When the model
1030 // is absent from the catalogue (or carries no price table) the cost is
1031 // silently 0 even though tokens were spent; warn so the otherwise-
1032 // invisible "uncatalogued model bills $0" leak is at least observable
1033 // in logs and any spend guardrail built on top of it.
1034 var messageCost float64
1035 if cost != nil {
1036 messageCost = *cost
1037 } else if usageHasTokens(res.Usage) {
1038 slog.Warn("Model is missing from the pricing catalogue; recording $0 cost despite token usage",
1039 "agent", a.Name(),
1040 "model", modelID,
1041 "input_tokens", res.Usage.InputTokens,
1042 "output_tokens", res.Usage.OutputTokens,
1043 "cached_input_tokens", res.Usage.CachedInputTokens,
1044 "cache_write_tokens", res.Usage.CacheWriteTokens)
1045 }
1046
1047 messageModel := modelID
1048
1049 assistantMessage := chat.Message{
1050 Role: chat.MessageRoleAssistant,
1051 Content: res.Content,
1052 ReasoningContent: res.ReasoningContent,
1053 ThinkingSignature: res.ThinkingSignature,
1054 ThoughtSignature: res.ThoughtSignature,
1055 ToolCalls: res.Calls,
1056 ToolDefinitions: toolDefs,

Callers 1

runTurnMethod · 0.95

Calls 7

usageHasTokensFunction · 0.85
addAgentMessageFunction · 0.85
DebugMethod · 0.80
WarnMethod · 0.80
nowMethod · 0.80
GetAllMessagesMethod · 0.80
NameMethod · 0.65

Tested by

no test coverage detected