Skip to content

Understand content types with XMTP

When you build an agent with XMTP, all messages are encoded with a content type to ensure that an XMTP client knows how to encode and decode messages, ensuring interoperability and consistent display of messages across apps.

In addition, message payloads are transported as a set of bytes. This means that payloads can carry any content type that a client supports, such as plain text, JSON, or even non-text binary or media content.

At a high level, there are these categories of content types with XMTP:

  • Standard
  • Custom

Standard content types

A standard content type is one that has undergone the XMTP Request for Comment (XRC) process and has been adopted as an XMTP Improvement Proposal (XIP).

All standard content types are built into the Agent SDK and can be used with dedicated send methods:

Custom content types

Custom content types allow you to define your own schemas for messages that go beyond what is covered by standard content types. These are useful for experiments, domain-specific features, or app-specific behaviors.

Writing custom codecs

A content type needs a codec which must satisfy the ContentCodec interface from @xmtp/content-type-primitives.

Example:

import type {
  ContentCodec,
  ContentTypeId,
  EncodedContent,
} from '@xmtp/content-type-primitives';
 
// Define the content type identifier
export const CustomContentType: ContentTypeId = {
  authorityId: 'your-domain.com',
  typeId: 'your-custom-id',
  versionMajor: 1,
  versionMinor: 0,
};
 
// Implement the codec as a class
export class CustomCodec implements ContentCodec<string> {
  contentType = CustomContentType;
 
  encode(content: string): EncodedContent {
    return {
      type: this.contentType,
      parameters: {},
      content: new TextEncoder().encode(content),
    };
  }
 
  decode(content: EncodedContent): string {
    return new TextDecoder().decode(content.content);
  }
 
  fallback(content: string): string | undefined {
    return content;
  }
 
  shouldPush(): boolean {
    return false;
  }
}

Registering custom codecs

Pass codec instances to Agent.create():

import { Agent } from '@xmtp/agent-sdk';
 
const client = await Agent.create(signer, {
  codecs: [new CustomCodec()],
});

Sending custom content

Encode the content using your codec, then pass the encoded bytes to send():

const codec = new CustomCodec();
await conversation.send(codec.encode('Hello from custom type'));

Receiving custom content

The SDK automatically decodes incoming messages using the registered codecs. Access the decoded content via message.content:

const messages = await conversation.messages();
for (const message of messages) {
  if (message.type.sameAs(CustomContentType)) {
    console.log(message.content); // decoded type
  }
}