Skip to content

Python: Bug: AnnotationContent and StreamingAnnotationContent to_element writes CitationType.X, so annotations in a rendered chat history fail to parse #14590

Open

Description

Describe the bug

AnnotationContent.to_element() and StreamingAnnotationContent.to_element() store the CitationType enum object in the XML attribute:

if self.citation_type:
    element.set("type", self.citation_type)

CitationType is a str, Enum. When the element is serialized, the attribute is written with the enum's str() form, CitationType.FILE_CITATION, not the value file_citation. from_element() then cannot read it back. Any chat message that has an annotation with a citation type breaks as soon as the history is rendered to a prompt string and parsed back (ChatHistory.from_rendered_prompt, which is what prompt templates use for {{$chat_history}} style messages).

The existing round trip tests pass because they never serialize the element to a string, so the enum object stays in memory.

To Reproduce

Run against current main (5b4a326), Python 3.13:

from semantic_kernel.contents import ChatHistory, ChatMessageContent, AuthorRole, TextContent
from semantic_kernel.contents.annotation_content import AnnotationContent, CitationType

msg = ChatMessageContent(
    role=AuthorRole.ASSISTANT,
    items=[
        TextContent(text="see [1]"),
        AnnotationContent(file_id="file-1", quote="q", start_index=4, end_index=7, citation_type=CitationType.FILE_CITATION),
    ],
)
history = ChatHistory(messages=[msg])
print(msg.to_prompt())
ChatHistory.from_rendered_prompt(str(history))

Output:

<message role="assistant"><text>see [1]</text><annotation type="CitationType.FILE_CITATION" file_id="file-1" quote="q" start_index="4" end_index="7"></annotation></message>
pydantic_core._pydantic_core.ValidationError: 1 validation error for AnnotationContent
type
  Input should be 'url_citation', 'file_path', 'file_citation' or 'container_file_citation' [type=enum, input_value='CitationType.FILE_CITATION', input_type=str]

StreamingAnnotationContent has the same line and fails the same way:

from xml.etree.ElementTree import tostring, fromstring
from semantic_kernel.contents.streaming_annotation_content import StreamingAnnotationContent
c = StreamingAnnotationContent(file_id="f", citation_type=CitationType.FILE_CITATION)
StreamingAnnotationContent.from_element(fromstring(tostring(c.to_element(), encoding="unicode")))

Expected behavior

The attribute should be written as the enum value (type="file_citation") so that from_element can parse it. The fix is to use self.citation_type.value in both to_element methods.

I have a fix with tests ready and can open a PR.

Platform

  • Language: Python
  • Source: main branch (5b4a326)
  • OS: Windows, Python 3.13

Activity

  1. added a commit that references this issue on Oct 13, 2026
    0a2f63e
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

    pythonPull requests for the Python Semantic Kerneltriage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions