> ## Documentation Index
> Fetch the complete documentation index at: https://docs.maximem.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# conversation.record_message

> Record a single conversation message (user or assistant turn) into Synap.

```python theme={null}
await sdk.conversation.record_message(
    conversation_id: str,
    role: str,
    content: str,
    user_id: str,
    customer_id: Optional[str] = None,
    session_id: Optional[str] = None,
    metadata: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]
```

Records a single message turn against a conversation. Synap uses recorded messages to build conversation-scoped context (facts, preferences, episodes) and as input for compaction. Both `user` and `assistant` turns should be recorded so the system has the full transcript.

### Parameters

<ParamField path="conversation_id" type="str" required={true}>
  Stable identifier for the conversation. All messages sharing the same `conversation_id` form one transcript. Must be a valid UUID: generate one with `str(uuid.uuid4())` and reuse it for every turn in the conversation. This call is [what registers a conversation](/concepts/context-end-to-end#short-term-context).
</ParamField>

<ParamField path="role" type="str" required={true}>
  Message role. Must be `"user"` or `"assistant"`.
</ParamField>

<ParamField path="content" type="str" required={true}>
  The message text.
</ParamField>

<ParamField path="user_id" type="str" required={true}>
  External user identifier (your application's user ID). Required so the message is scoped to the right end user.
</ParamField>

<ParamField path="customer_id" type="str" required={false}>
  External customer/tenant identifier.

  Required on B2B; auto-resolved on B2C. See [B2C vs B2B](/concepts/memory-scopes#b2c-vs-b2b-which-scopes-apply-to-you). **Required for B2B instances** (multi-tenant), where each message must be scoped to a tenant. **Optional for B2C instances**, where the customer is auto-resolved from the user. If omitted, Synap derives it automatically. Passing it on a B2C instance is harmless but unnecessary.
</ParamField>

<ParamField path="session_id" type="str" required={false}>
  Optional session identifier. Auto-generated if not provided.
</ParamField>

<ParamField path="metadata" type="Dict[str, Any]" required={false}>
  Free-form metadata to attach to the message (e.g., model name, latency, custom tags).
</ParamField>

### Returns

A dict describing the recorded message.

<ResponseField name="message_id" type="str">Server-assigned message identifier.</ResponseField>
<ResponseField name="conversation_id" type="str">Echo of the supplied conversation id.</ResponseField>
<ResponseField name="session_id" type="str">Session id (the one you passed, or the auto-generated one).</ResponseField>
<ResponseField name="recorded_at" type="str">ISO-8601 timestamp of when the message was accepted.</ResponseField>

### Example

```python theme={null}
import uuid
from maximem_synap import MaximemSynapSDK

sdk = MaximemSynapSDK(api_key="synap_your_key_here")
await sdk.initialize()

# conversation_id must be a valid UUID; generate once and reuse for the whole transcript
conversation_id = str(uuid.uuid4())

await sdk.conversation.record_message(
    conversation_id=conversation_id,
    role="user",
    content="I prefer dark mode and concise answers.",
    user_id="user_alice",
    customer_id="customer_acme",  # required for B2B; omit on B2C (auto-resolved)
    metadata={"channel": "web"},
)

await sdk.conversation.record_message(
    conversation_id=conversation_id,
    role="assistant",
    content="Got it. I'll keep answers short and assume dark mode.",
    user_id="user_alice",
    customer_id="customer_acme",
)
```

### Raises

* `InvalidInputError`: when `role` is not `"user"` or `"assistant"`, or when required identifiers are missing.
* `AuthenticationError`: when the API key is missing or invalid.
* `NetworkError`: when the SDK cannot reach Synap.

### See also

* [conversation.record\_messages\_batch](/sdk-reference/conversation/record-messages-batch)
* [conversation.context.fetch](/sdk-reference/conversation-context/fetch)
* [conversation.context.compact](/sdk-reference/conversation-context/compact)
