Skip to content

Chat messages

We support 4 types of message objects:

  • SystemMessage: Instructions and context for the conversation
  • UserMessage: Messages from end users to the assistant
  • AssistantMessage: Responses from the AI assistant, potentially including tool calls
  • ToolMessage: Results from tools invoked during the conversation

Notes on the construction of messages:

  • Each message has a content field, which can either be a str or a list of Content objects with text and/or reasoning. We don't support audio/image/video content yet.
  • AssistantMessage objects also have a tool_calls field, which supports a list of ToolCall objects.

Usage

The easiest way to convert a dict into a ChatMessage is to use parse_chat_message:

from docent.data_models.chat import parse_chat_message

message_data = [
    {
        "role": "user",
        "content": "What is the capital of France?",
    },
    {
        "role": "assistant",
        "content": "Paris",
    },
]

messages = [parse_chat_message(msg) for msg in message_data]

The function will automatically raise validation errors if the input message does not conform to the schema.

You may also want to create messages manually:

from docent.data_models.chat import (
    SystemMessage,
    UserMessage,
    AssistantMessage,
    ContentText,
    ContentReasoning,
    ToolCall,
    ToolCallContent,
)

messages = [
    SystemMessage(content="You are a helpful assistant."),
    UserMessage(content=[ContentText(text="Help me with this problem.")]),
    AssistantMessage(content="I'll help you solve that.", tool_calls=[ToolCall(id="call_123", function="calculator", arguments={"operation": "add", "a": 5, "b": 3}, view=ToolCallContent(format="markdown", content="Calculating: 5 + 3"))]),
    ToolMessage(content="8", tool_call_id="call_123", function="calculator"),
]

docent.data_models.chat.message

ChatMessage module-attribute

ChatMessage = Annotated[SystemMessage | UserMessage | AssistantMessage | ToolMessage, Discriminator('role')]

Type alias for any chat message type, discriminated by the role field.

BaseChatMessage

Bases: BaseModel

Base class for all chat message types.

Attributes:

Name Type Description
id str | None

Optional unique identifier for the message.

content str | list[Content]

The message content, either as a string or list of Content objects.

role Literal['system', 'user', 'assistant', 'tool']

The role of the message sender (system, user, assistant, tool).

Source code in docent/data_models/chat/message.py
class BaseChatMessage(BaseModel):
    """Base class for all chat message types.

    Attributes:
        id: Optional unique identifier for the message.
        content: The message content, either as a string or list of Content objects.
        role: The role of the message sender (system, user, assistant, tool).
    """

    id: str | None = None
    content: str | list[Content]
    role: Literal["system", "user", "assistant", "tool"]

    @property
    def text(self) -> str:
        """Get the text content of the message.

        Returns:
            str: The text content of the message. If content is a list,
                 concatenates all text content elements with newlines.
        """
        if isinstance(self.content, str):
            return self.content
        else:
            all_text = [content.text for content in self.content if content.type == "text"]
            return "\n".join(all_text)

text property

text: str

Get the text content of the message.

Returns:

Name Type Description
str str

The text content of the message. If content is a list, concatenates all text content elements with newlines.

SystemMessage

Bases: BaseChatMessage

System message in a chat conversation.

Attributes:

Name Type Description
role Literal['system']

Always set to "system".

Source code in docent/data_models/chat/message.py
class SystemMessage(BaseChatMessage):
    """System message in a chat conversation.

    Attributes:
        role: Always set to "system".
    """

    role: Literal["system"] = "system"  # type: ignore

text property

text: str

Get the text content of the message.

Returns:

Name Type Description
str str

The text content of the message. If content is a list, concatenates all text content elements with newlines.

UserMessage

Bases: BaseChatMessage

User message in a chat conversation.

Attributes:

Name Type Description
role Literal['user']

Always set to "user".

tool_call_id list[str] | None

Optional list of tool call IDs this message is responding to.

Source code in docent/data_models/chat/message.py
class UserMessage(BaseChatMessage):
    """User message in a chat conversation.

    Attributes:
        role: Always set to "user".
        tool_call_id: Optional list of tool call IDs this message is responding to.
    """

    role: Literal["user"] = "user"  # type: ignore
    tool_call_id: list[str] | None = None

text property

text: str

Get the text content of the message.

Returns:

Name Type Description
str str

The text content of the message. If content is a list, concatenates all text content elements with newlines.

AssistantMessage

Bases: BaseChatMessage

Assistant message in a chat conversation.

Attributes:

Name Type Description
role Literal['assistant']

Always set to "assistant".

model str | None

Optional identifier for the model that generated this message.

tool_calls list[ToolCall] | None

Optional list of tool calls made by the assistant.

Source code in docent/data_models/chat/message.py
class AssistantMessage(BaseChatMessage):
    """Assistant message in a chat conversation.

    Attributes:
        role: Always set to "assistant".
        model: Optional identifier for the model that generated this message.
        tool_calls: Optional list of tool calls made by the assistant.
    """

    role: Literal["assistant"] = "assistant"  # type: ignore
    model: str | None = None
    tool_calls: list[ToolCall] | None = None

text property

text: str

Get the text content of the message.

Returns:

Name Type Description
str str

The text content of the message. If content is a list, concatenates all text content elements with newlines.

ToolMessage

Bases: BaseChatMessage

Tool message in a chat conversation.

Attributes:

Name Type Description
role Literal['tool']

Always set to "tool".

tool_call_id str | None

Optional ID of the tool call this message is responding to.

function str | None

Optional name of the function that was called.

error dict[str, Any] | None

Optional error information if the tool call failed.

Source code in docent/data_models/chat/message.py
class ToolMessage(BaseChatMessage):
    """Tool message in a chat conversation.

    Attributes:
        role: Always set to "tool".
        tool_call_id: Optional ID of the tool call this message is responding to.
        function: Optional name of the function that was called.
        error: Optional error information if the tool call failed.
    """

    role: Literal["tool"] = "tool"  # type: ignore

    tool_call_id: str | None = None
    function: str | None = None
    error: dict[str, Any] | None = None

text property

text: str

Get the text content of the message.

Returns:

Name Type Description
str str

The text content of the message. If content is a list, concatenates all text content elements with newlines.

parse_chat_message

parse_chat_message(message_data: dict[str, Any] | ChatMessage) -> ChatMessage

Parse a message dictionary or object into the appropriate ChatMessage subclass.

Parameters:

Name Type Description Default
message_data dict[str, Any] | ChatMessage

A dictionary or ChatMessage object representing a chat message.

required

Returns:

Name Type Description
ChatMessage ChatMessage

An instance of a ChatMessage subclass based on the role.

Raises:

Type Description
ValueError

If the message role is unknown.

Source code in docent/data_models/chat/message.py
def parse_chat_message(message_data: dict[str, Any] | ChatMessage) -> ChatMessage:
    """Parse a message dictionary or object into the appropriate ChatMessage subclass.

    Args:
        message_data: A dictionary or ChatMessage object representing a chat message.

    Returns:
        ChatMessage: An instance of a ChatMessage subclass based on the role.

    Raises:
        ValueError: If the message role is unknown.
    """
    if isinstance(message_data, (SystemMessage, UserMessage, AssistantMessage, ToolMessage)):
        return message_data

    role = message_data.get("role")
    if role == "system":
        return SystemMessage.model_validate(message_data)
    elif role == "user":
        return UserMessage.model_validate(message_data)
    elif role == "assistant":
        return AssistantMessage.model_validate(message_data)
    elif role == "tool":
        return ToolMessage.model_validate(message_data)
    else:
        raise ValueError(f"Unknown message role: {role}")

docent.data_models.chat.content

Content module-attribute

Content = Annotated[ContentText | ContentReasoning, Discriminator('type')]

Discriminated union of possible content types using the 'type' field. Can be either ContentText or ContentReasoning.

BaseContent

Bases: BaseModel

Base class for all content types in chat messages.

Provides the foundation for different content types with a discriminator field.

Attributes:

Name Type Description
type Literal['text', 'reasoning', 'image', 'audio', 'video']

The content type identifier, used for discriminating between content types.

Source code in docent/data_models/chat/content.py
class BaseContent(BaseModel):
    """Base class for all content types in chat messages.

    Provides the foundation for different content types with a discriminator field.

    Attributes:
        type: The content type identifier, used for discriminating between content types.
    """

    type: Literal["text", "reasoning", "image", "audio", "video"]

ContentText

Bases: BaseContent

Text content for chat messages.

Represents plain text content in a chat message.

Attributes:

Name Type Description
type Literal['text']

Fixed as "text" to identify this content type.

text str

The actual text content.

refusal bool | None

Optional flag indicating if this is a refusal message.

Source code in docent/data_models/chat/content.py
class ContentText(BaseContent):
    """Text content for chat messages.

    Represents plain text content in a chat message.

    Attributes:
        type: Fixed as "text" to identify this content type.
        text: The actual text content.
        refusal: Optional flag indicating if this is a refusal message.
    """

    type: Literal["text"] = "text"  # type: ignore
    text: str
    refusal: bool | None = None

ContentReasoning

Bases: BaseContent

Reasoning content for chat messages.

Represents reasoning or thought process content in a chat message.

Attributes:

Name Type Description
type Literal['reasoning']

Fixed as "reasoning" to identify this content type.

reasoning str

The actual reasoning text.

signature str | None

Optional signature associated with the reasoning.

redacted bool

Flag indicating if the reasoning has been redacted.

Source code in docent/data_models/chat/content.py
class ContentReasoning(BaseContent):
    """Reasoning content for chat messages.

    Represents reasoning or thought process content in a chat message.

    Attributes:
        type: Fixed as "reasoning" to identify this content type.
        reasoning: The actual reasoning text.
        signature: Optional signature associated with the reasoning.
        redacted: Flag indicating if the reasoning has been redacted.
    """

    type: Literal["reasoning"] = "reasoning"  # type: ignore
    reasoning: str
    signature: str | None = None
    redacted: bool = False

docent.data_models.chat.tool

ToolCall dataclass

Tool call information.

Attributes:

Name Type Description
id str

Unique identifier for tool call.

type Literal['function'] | None

Type of tool call. Can only be "function" or None.

function str

Function called.

arguments dict[str, Any]

Arguments to function.

parse_error str | None

Error which occurred parsing tool call.

view ToolCallContent | None

Custom view of tool call input.

Source code in docent/data_models/chat/tool.py
@dataclass
class ToolCall:
    """Tool call information.

    Attributes:
        id: Unique identifier for tool call.
        type: Type of tool call. Can only be "function" or None.
        function: Function called.
        arguments: Arguments to function.
        parse_error: Error which occurred parsing tool call.
        view: Custom view of tool call input.
    """

    id: str
    type: Literal["function"] | None
    function: str
    arguments: dict[str, Any]
    parse_error: str | None = None
    view: ToolCallContent | None = None

ToolCallContent

Bases: BaseModel

Content to include in tool call view.

Attributes:

Name Type Description
title str | None

Optional (plain text) title for tool call content.

format Literal['text', 'markdown']

Format (text or markdown).

content str

Text or markdown content.

Source code in docent/data_models/chat/tool.py
class ToolCallContent(BaseModel):
    """Content to include in tool call view.

    Attributes:
        title: Optional (plain text) title for tool call content.
        format: Format (text or markdown).
        content: Text or markdown content.
    """

    title: str | None = None
    format: Literal["text", "markdown"]
    content: str

ToolParam

Bases: BaseModel

A parameter for a tool function.

Parameters:

Name Type Description Default
name

The name of the parameter.

required
description

A description of what the parameter does.

required
input_schema

JSON Schema describing the parameter's type and validation rules.

required
Source code in docent/data_models/chat/tool.py
class ToolParam(BaseModel):
    """A parameter for a tool function.

    Args:
        name: The name of the parameter.
        description: A description of what the parameter does.
        input_schema: JSON Schema describing the parameter's type and validation rules.
    """

    name: str
    description: str
    input_schema: dict[str, Any]

ToolParams

Bases: BaseModel

Description of tool parameters object in JSON Schema format.

Parameters:

Name Type Description Default
type

The type of the parameters object, always 'object'.

required
properties

Dictionary mapping parameter names to their ToolParam definitions.

required
required

List of required parameter names.

required
additionalProperties

Whether additional properties are allowed beyond those specified. Always False.

required
Source code in docent/data_models/chat/tool.py
class ToolParams(BaseModel):
    """Description of tool parameters object in JSON Schema format.

    Args:
        type: The type of the parameters object, always 'object'.
        properties: Dictionary mapping parameter names to their ToolParam definitions.
        required: List of required parameter names.
        additionalProperties: Whether additional properties are allowed beyond those
            specified. Always False.
    """

    type: Literal["object"] = "object"
    properties: dict[str, ToolParam] = Field(default_factory=dict)
    required: list[str] = Field(default_factory=list)
    additionalProperties: bool = False

ToolInfo

Bases: BaseModel

Specification of a tool (JSON Schema compatible).

If you are implementing a ModelAPI, most LLM libraries can be passed this object (dumped to a dict) directly as a function specification. For example, in the OpenAI provider:

ChatCompletionToolParam(
    type="function",
    function=tool.model_dump(exclude_none=True),
)

In some cases the field names don't match up exactly. In that case call model_dump() on the parameters field. For example, in the Anthropic provider:

ToolParam(
    name=tool.name,
    description=tool.description,
    input_schema=tool.parameters.model_dump(exclude_none=True),
)

Attributes:

Name Type Description
name str

Name of tool.

description str

Short description of tool.

parameters ToolParams

JSON Schema of tool parameters object.

Source code in docent/data_models/chat/tool.py
class ToolInfo(BaseModel):
    """Specification of a tool (JSON Schema compatible).

    If you are implementing a ModelAPI, most LLM libraries can
    be passed this object (dumped to a dict) directly as a function
    specification. For example, in the OpenAI provider:

    ```python
    ChatCompletionToolParam(
        type="function",
        function=tool.model_dump(exclude_none=True),
    )
    ```

    In some cases the field names don't match up exactly. In that case
    call `model_dump()` on the `parameters` field. For example, in the
    Anthropic provider:

    ```python
    ToolParam(
        name=tool.name,
        description=tool.description,
        input_schema=tool.parameters.model_dump(exclude_none=True),
    )
    ```

    Attributes:
        name: Name of tool.
        description: Short description of tool.
        parameters: JSON Schema of tool parameters object.
    """

    name: str
    description: str
    parameters: ToolParams = Field(default_factory=ToolParams)