Skip to content

[firebase_ai]: TemplateChatSession.sendMessage drops auto-executed function call/response turns from history #18757

Description

@widarlein

Is there an existing issue for this?

  • I have searched the existing issues.

Which plugins are affected?

Other

Which platforms are affected?

Web

Description

Affected plugin: firebase_ai (not in the dropdown). The code is pure Dart, so other platforms are likely affected too; we have only built for Web.

When TemplateChatSession.sendMessage auto-executes functions (TemplateAutoFunctionDeclaration), only the original message and the final model response are added to history:

// lib/src/server_template/template_chat.dart, sendMessage
if (!shouldAutoExecute) {
  if (response.candidates case [final candidate, ...]) {
    _history.add(message);
    // ...
    _history.add(normalizedContent);
  }
  return response;
}

The intermediate turns collected in requestHistory are discarded: the model's functionCall content and the function responses. On the next sendMessage, the model no longer sees what its tools returned. For example, a createCharacter call that returned a new id is gone from history, so a follow-up call that needs that id has nothing to refer to.

The other three code paths keep the whole exchange with _history.addAll(requestHistory):

  • TemplateChatSession.sendMessageStream
  • ChatSession.sendMessage
  • ChatSession.sendMessageStream

So this looks like an oversight in this one path rather than intended behavior.

Expected: after auto-executed function turns, history contains the user message, each model functionCall turn, each function response turn and the final response, as sendMessageStream does. Likely fix:

_history.addAll(requestHistory);
_history.add(normalizedContent);

Actual: history contains only the user message and the final response.

This is still the code on main as of today. We found it while building function calling on a server prompt template, and worked around it by using sendMessageStream.

Reproducing the issue

  1. Create a server prompt template that declares one function, e.g. getValue, and includes {{history}}.
  2. final chat = FirebaseAI.googleAI().templateGenerativeModel().startChat('<template-id>', inputs: {}, tools: [TemplateTool.functionDeclarations([TemplateAutoFunctionDeclaration(name: 'getValue', parameters: {}, callable: (_) => {'value': 42})])]);
  3. await chat.sendMessage(Content.text('Call getValue and tell me the result.')); The model calls the function and the SDK auto-executes it.
  4. Inspect chat.history: it has 2 entries (user message, final reply). The functionCall and functionResponse turns are missing. Doing the same with sendMessageStream gives 4 entries.

Firebase Core version

4.14.0

Flutter Version

3.44.1

Relevant Log Output

No error is raised; the turns are silently missing from `chat.history`.

Flutter dependencies

Expand Flutter dependencies snippet
firebase_ai: 4.0.0
firebase_core: 4.14.0

Additional context and comments

Related, but already fixed on main in 6eb250f (#18685), not yet released: in 4.0.0, function responses are sent with role function, which the template endpoint rejects with Role 'function' is not supported. Please use a valid role: SYSTEM, SYSTEM_1, USER, ASSISTANT, DEVELOPER, CONTEXT, USER_CONTEXT, MODEL, USER. Mentioned only so it isn't re-reported. A release including that fix would be welcome.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs AttentionThis issue needs maintainer attention.platform: webIssues / PRs which are specifically for web.plugin: ailabel issues for firebase_ai plugintype: bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions