diff --git a/integrations/gaia/.env.example b/integrations/gaia/.env.example
new file mode 100644
index 0000000..58ab873
--- /dev/null
+++ b/integrations/gaia/.env.example
@@ -0,0 +1,4 @@
+#GAIA Integration
+GAIA_NODE_URL= # the URL of the Gaia node (Ex: https://llama8b.gaia.domains/v1)
+GAIA_API_KEY= # the API key for the Gaia node (Ex: gaia-xxxxxxxxxx)
+GAIA_MODEL_NAME= # the name of model running on your Gaia node (Ex: llama)
\ No newline at end of file
diff --git a/integrations/gaia/README.md b/integrations/gaia/README.md
new file mode 100644
index 0000000..b3bdbca
--- /dev/null
+++ b/integrations/gaia/README.md
@@ -0,0 +1,148 @@
+# Gaia agent example
+
+This example uses a [Gaia](https://docs.gaianet.ai) API for AI based responses and [XMTP](https://xmtp.org) for secure messaging. You can test your agent on [xmtp.chat](https://xmtp.chat) or any other XMTP-compatible client.
+
+Using Gaia, you can also run your own [node](https://docs.gaianet.ai/getting-started/quick-start) and use the OpenAI compatible API in this library.
+
+## Environment variables
+
+Add the following keys to a `.env` file:
+
+```bash
+WALLET_KEY= # the private key of the wallet
+ENCRYPTION_KEY= # a second random 32 bytes encryption key for local db encryption
+GAIA_API_KEY= # Your API key from https://gaianet.ai
+GAIA_NODE_URL= # Your custom Gaia node URL or a public node, ex: https://llama8b.gaia.domains/v1
+GAIA_MODEL_NAME= # Model name running in your Gaia node or a public node, ex: llama
+```
+
+You can generate random keys with the following command:
+
+```bash
+yarn gen:keys
+```
+
+> [!WARNING]
+> Running the `gen:keys` script will overwrite the existing `.env` file.
+
+## Usage
+
+```tsx
+import { Client, type XmtpEnv } from "@xmtp/node-sdk";
+import OpenAI from "openai";
+import { createSigner, getEncryptionKeyFromHex } from "@/helpers";
+
+const { WALLET_KEY, ENCRYPTION_KEY, GAIA_NODE_URL, GAIA_API_KEY, GAIA_MODEL_NAME } = process.env;
+
+if (!WALLET_KEY) {
+  throw new Error("WALLET_KEY must be set");
+}
+
+if (!ENCRYPTION_KEY) {
+  throw new Error("ENCRYPTION_KEY must be set");
+}
+
+/* Check if the Gaia API key is set */
+if (!GAIA_API_KEY) {
+  throw new Error("GAIA_API_KEY must be set");
+}
+
+/* Check if the Gaia node's base URL is set */
+if (!GAIA_NODE_URL) {
+  throw new Error("GAIA_NODE_URL must be set");
+}
+
+/* Check if the the model name for the Gaia node is set */
+if (!GAIA_MODEL_NAME) {
+  throw new Error("GAIA_MODEL_NAME must be set");
+}
+
+const signer = createSigner(WALLET_KEY);
+const encryptionKey = getEncryptionKeyFromHex(ENCRYPTION_KEY);
+const openai = new OpenAI({ 
+    baseURL: GAIA_NODE_URL,
+    apiKey: GAIA_API_KEY
+});
+
+/* Set the environment to dev or production */
+const env: XmtpEnv = "dev";
+
+async function main() {
+  console.log(`Creating client on the '${env}' network...`);
+  const client = await Client.create(signer, encryptionKey, {
+    env,
+  });
+
+  console.log("Syncing conversations...");
+  /* Sync the conversations from the network to update the local db */
+  await client.conversations.sync();
+
+  console.log(
+    `Agent initialized on ${client.accountAddress}\nSend a message on http://xmtp.chat/dm/${client.accountAddress}`,
+  );
+
+  console.log("Waiting for messages...");
+  const stream = client.conversations.streamAllMessages();
+
+  for await (const message of await stream) {
+    /* Ignore messages from the same agent or non-text messages */
+    if (
+      message?.senderInboxId.toLowerCase() === client.inboxId.toLowerCase() ||
+      message?.contentType?.typeId !== "text"
+    ) {
+      continue;
+    }
+
+    console.log(
+      `Received message: ${message.content as string} by ${message.senderInboxId}`,
+    );
+
+    const conversation = client.conversations.getConversationById(
+      message.conversationId,
+    );
+
+    if (!conversation) {
+      console.log("Unable to find conversation, skipping");
+      continue;
+    }
+
+    try {
+      const completion = await openai.chat.completions.create({
+        messages: [{ role: "user", content: message.content as string }],
+        model: GAIA_MODEL_NAME,
+      });
+
+      /* Get the AI response */
+      const response =
+        completion.choices[0]?.message?.content ||
+        "I'm not sure how to respond to that.";
+
+      console.log(`Sending AI response: ${response}`);
+      await conversation.send(response);
+    } catch (error) {
+      console.error("Error getting AI response:", error);
+      await conversation.send(
+        "Sorry, I encountered an error processing your message.",
+      );
+    }
+
+    console.log("Waiting for messages...");
+  }
+}
+
+main().catch(console.error);
+```
+
+## Run the agent
+
+```bash
+# git clone repo
+git clone https://github.com/ephemeraHQ/xmtp-agent-examples.git
+# go to the folder
+cd xmtp-agent-examples
+# install packages
+yarn
+
+cd integrations/gaia
+yarn dev
+```
diff --git a/integrations/gaia/index.ts b/integrations/gaia/index.ts
new file mode 100644
index 0000000..d4d96f0
--- /dev/null
+++ b/integrations/gaia/index.ts
@@ -0,0 +1,126 @@
+import { Client, type XmtpEnv } from "@xmtp/node-sdk";
+import OpenAI from "openai";
+import { createSigner, getEncryptionKeyFromHex } from "@/helpers";
+
+/* Get the wallet key associated to the public key of
+ * the agent and the encryption key for the local db
+ * that stores your agent's messages */
+const {
+  WALLET_KEY,
+  ENCRYPTION_KEY,
+  GAIA_NODE_URL,
+  GAIA_API_KEY,
+  GAIA_MODEL_NAME,
+} = process.env;
+
+/* Check if the environment variables are set */
+if (!WALLET_KEY) {
+  throw new Error("WALLET_KEY must be set");
+}
+
+/* Check if the encryption key is set */
+if (!ENCRYPTION_KEY) {
+  throw new Error("ENCRYPTION_KEY must be set");
+}
+
+/* Check if the OpenAI API key is set */
+if (!GAIA_API_KEY) {
+  throw new Error("GAIA_API_KEY must be set");
+}
+
+/* Check if the Gaia node's base URL is set */
+if (!GAIA_NODE_URL) {
+  throw new Error("GAIA_NODE_URL must be set");
+}
+
+/* Check if the the model name for the Gaia node is set */
+if (!GAIA_MODEL_NAME) {
+  throw new Error("GAIA_MODEL_NAME must be set");
+}
+
+/* Create the signer using viem and parse the encryption key for the local db */
+const signer = createSigner(WALLET_KEY);
+const encryptionKey = getEncryptionKeyFromHex(ENCRYPTION_KEY);
+
+/* Initialize the OpenAI client */
+const openai = new OpenAI({
+  baseURL: GAIA_NODE_URL,
+  apiKey: GAIA_API_KEY,
+});
+
+/* Set the environment to dev or production */
+const env: XmtpEnv = "dev";
+
+/**
+ * Main function to run the agent
+ */
+async function main() {
+  console.log(`Creating client on the '${env}' network...`);
+  /* Initialize the xmtp client */
+  const client = await Client.create(signer, encryptionKey, {
+    env,
+  });
+
+  console.log("Syncing conversations...");
+  /* Sync the conversations from the network to update the local db */
+  await client.conversations.sync();
+
+  console.log(
+    `Agent initialized on ${client.accountAddress}\nSend a message on http://xmtp.chat/dm/${client.accountAddress}`,
+  );
+
+  console.log("Waiting for messages...");
+  /* Stream all messages from the network */
+  const stream = client.conversations.streamAllMessages();
+
+  for await (const message of await stream) {
+    /* Ignore messages from the same agent or non-text messages */
+    if (
+      message?.senderInboxId.toLowerCase() === client.inboxId.toLowerCase() ||
+      message?.contentType?.typeId !== "text"
+    ) {
+      continue;
+    }
+
+    console.log(
+      `Received message: ${message.content as string} by ${message.senderInboxId}`,
+    );
+
+    /* Get the conversation from the local db */
+    const conversation = client.conversations.getDmByInboxId(
+      message.senderInboxId,
+    );
+
+    /* If the conversation is not found, skip the message */
+    if (!conversation) {
+      console.log("Unable to find conversation, skipping");
+      continue;
+    }
+
+    try {
+      /* Get the AI response */
+      const completion = await openai.chat.completions.create({
+        messages: [{ role: "user", content: message.content as string }],
+        model: GAIA_MODEL_NAME as string,
+      });
+
+      /* Get the AI response */
+      const response =
+        completion.choices[0]?.message?.content ||
+        "I'm not sure how to respond to that.";
+
+      console.log(`Sending AI response: ${response}`);
+      /* Send the AI response to the conversation */
+      await conversation.send(response);
+    } catch (error) {
+      console.error("Error getting AI response:", error);
+      await conversation.send(
+        "Sorry, I encountered an error processing your message.",
+      );
+    }
+
+    console.log("Waiting for messages...");
+  }
+}
+
+main().catch(console.error);
diff --git a/integrations/gaia/package.json b/integrations/gaia/package.json
new file mode 100644
index 0000000..db0dc9e
--- /dev/null
+++ b/integrations/gaia/package.json
@@ -0,0 +1,20 @@
+{
+  "name": "@integrations/gaia",
+  "version": "0.0.1",
+  "private": true,
+  "type": "module",
+  "scripts": {
+    "dev": "tsx --env-file=.env index.ts",
+    "gen:keys": "tsx ../../scripts/generateKeys.ts"
+  },
+  "dependencies": {
+    "@xmtp/node-sdk": "0.0.47",
+    "tsx": "^4.19.2",
+    "uint8arrays": "^5.1.0",
+    "viem": "^2.22.17"
+  },
+  "packageManager": "yarn@4.6.0",
+  "engines": {
+    "node": ">=20"
+  }
+}
diff --git a/yarn.lock b/yarn.lock
index c1e12f0..19e3357 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -808,6 +808,17 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@integrations/gaia@workspace:integrations/gaia":
+  version: 0.0.0-use.local
+  resolution: "@integrations/gaia@workspace:integrations/gaia"
+  dependencies:
+    "@xmtp/node-sdk": "npm:0.0.47"
+    tsx: "npm:^4.19.2"
+    uint8arrays: "npm:^5.1.0"
+    viem: "npm:^2.22.17"
+  languageName: unknown
+  linkType: soft
+
 "@integrations/gpt@workspace:integrations/grok":
   version: 0.0.0-use.local
   resolution: "@integrations/gpt@workspace:integrations/grok"
@@ -1288,6 +1299,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@xmtp/node-bindings@npm:^0.0.41":
+  version: 0.0.41
+  resolution: "@xmtp/node-bindings@npm:0.0.41"
+  checksum: 10/809347d36de2b4f205fe46cc3869b1eab7595107fd14b0535457732745d14851121d1e7b0f22a0845deb32e48dfca29a7ad36a12bf9fc5c46b445a308a589c10
+  languageName: node
+  linkType: hard
+
 "@xmtp/node-sdk@npm:0.0.42":
   version: 0.0.42
   resolution: "@xmtp/node-sdk@npm:0.0.42"
@@ -1314,6 +1332,19 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@xmtp/node-sdk@npm:0.0.47":
+  version: 0.0.47
+  resolution: "@xmtp/node-sdk@npm:0.0.47"
+  dependencies:
+    "@xmtp/content-type-group-updated": "npm:^2.0.0"
+    "@xmtp/content-type-primitives": "npm:^2.0.0"
+    "@xmtp/content-type-text": "npm:^2.0.0"
+    "@xmtp/node-bindings": "npm:^0.0.41"
+    "@xmtp/proto": "npm:^3.72.3"
+  checksum: 10/bf3b5e59cc5be0b9ec02acd2d7cf59bcae5f478971b5ffc772e6153c8d59515032c95436faf2c741e1de334d9572dc1991098395d9813ec5364f0eb09666a815
+  languageName: node
+  linkType: hard
+
 "@xmtp/proto@npm:^3.72.0, @xmtp/proto@npm:^3.72.3":
   version: 3.73.0
   resolution: "@xmtp/proto@npm:3.73.0"