---
name: message
lang: py
domain: core
version: "1.0.0"
algebraic: product
definition: |
  @dataclass
  class Message:
      id: str
      role: str
      parts: list[Part]
      created_at: datetime | None = None
description: "Modelo de mensaje multipart para conversaciones con agentes. Soporta texto, referencias a contexto (memoria/recurso/skill) y llamadas a herramientas en un mensaje unificado. Disenado para ser serializable a JSONL para persistencia."
tags: [message, conversation, multipart, llm, agent, history, jsonl, serialization, tokens]
uses_types: [part_py_core, text_part_py_core, context_part_py_core, tool_part_py_core]
file_path: "python/types/core/message.py"
---

## Metodos

- `content` (property) — texto del primer `TextPart`. Vacio si no hay TextPart.
- `estimated_tokens` (property) — estimacion `ceil(total_chars / 4)`. Cuenta chars de TextParts, abstracts de ContextParts, y JSON de tool_input + tool_output de ToolParts.
- `to_dict() -> dict` — serializa a dict listo para `json.dumps()`. Timestamps en ISO 8601.
- `to_jsonl() -> str` — serializa a string JSON de una sola linea.
- `from_dict(data: dict) -> Message` (classmethod) — deserializa usando `part_from_dict()` para cada parte.
- `create_user(content: str) -> Message` (classmethod) — factory: role="user", un TextPart, UUID y timestamp UTC automaticos.
- `create_assistant(content, context_refs=None, tool_calls=None) -> Message` (classmethod) — factory: role="assistant", orden de partes: ContextParts → TextPart → ToolParts.
- `get_context_parts() -> list[ContextPart]` — filtra partes de tipo ContextPart.
- `get_tool_parts() -> list[ToolPart]` — filtra partes de tipo ToolPart.
- `find_tool_part(tool_id: str) -> ToolPart | None` — busca un ToolPart por tool_id.

## Notas

El campo `role` acepta "user" o "assistant" por convencion, pero no se valida — el tipo es abierto para compatibilidad con futuros roles (e.g., "system", "tool").

La estimacion de tokens (ceil(chars / 4)) es una heuristica. No sustituye a un tokenizador real, pero es util para presupuesto rapido sin dependencias externas.

`to_dict()` usa `dataclasses.asdict()` sobre cada Part, que serializa recursivamente incluyendo el campo `type` discriminador — esto garantiza que `from_dict()` puede reconstruir el tipo correcto.

Las factories `create_user` y `create_assistant` generan IDs con `uuid.uuid4()` y timestamps UTC automaticamente, simplificando la construccion en pipelines de conversacion.
