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

# Connect real-time events

> Connect Maven to a user's recent in-app activity via the Autoplay MCP server, with verified user identity.

## ⚡ Add this skill

<CardGroup cols={2}>
  <Card title="One command" icon="terminal">
    Add the Autoplay Maven skill for an existing Maven AI support agent setup.

    <CodeGroup>
      ```bash CLI theme={null}
      uvx --from autoplay-sdk autoplay-install-skills --chatbot maven
      ```
    </CodeGroup>

    <a className="skill-card-link" href="/recipes/maven/step-1-connect-real-time-events">View the docs →</a>
  </Card>

  <Card title="Agent onboarding" icon="robot">
    Fetch this skill when a customer already uses Maven and wants its AI support agent to consume Autoplay live user activity.

    <CodeGroup>
      ```bash cURL theme={null}
      curl -s https://developers.autoplay.ai/chatbot-maven/SKILL.md
      ```
    </CodeGroup>

    <a className="skill-card-link" href="https://developers.autoplay.ai/chatbot-maven/SKILL.md" target="_blank">View the skill →</a>
  </Card>
</CardGroup>

**Maven** pulls a user's recent in-app activity on demand via the **Autoplay MCP server** — it calls the tool the moment it needs context to answer. You'll do four things:

<Steps>
  <Step title="Connect Maven to the MCP server">
    So Maven can call the Autoplay MCP tools.
  </Step>

  <Step title="Tell Maven when to use live activity">
    So the agent checks user activity before it answers.
  </Step>

  <Step title="Embed the Maven chat widget">
    So your users can talk to Maven inside your app.
  </Step>

  <Step title="Pass a verified user identity">
    So Maven knows *which* user is asking, and pulls the right activity.
  </Step>
</Steps>

<Tip>
  This guide assumes you **already have a Maven agent created** in Agent Designer. If you don't have one yet, see [Maven AGI's Agent Designer docs](https://www.mavenagi.com/product/agent-designer) to create one first, then come back here.
</Tip>

**What Autoplay needs from your Maven setup:**

* **`product_id`** and **`mcp_key`** — printed by your own `onboard_product` call (see [Quickstart](/quickstart)), not something Maven issues.
* **Organization ID and Agent ID** (Chat app → Settings → Instructions tab) — only needed if you haven't embedded the widget yet; skip if it's already running.

## 🎬 Watch the walkthrough

Prefer to watch first? This short Loom covers **Part A below** — installing the MCP app on your Maven agent, configuring it with your MCP URL and token, and testing it in the Simulator.

<Frame>
  <iframe src="https://www.loom.com/embed/1f9cf62b4ee74d44bf34d5b6408e8a2f" title="Connect the Autoplay MCP server to Maven" frameBorder="0" allowFullScreen style={{ width: "100%", aspectRatio: "16 / 9", borderRadius: "12px" }} />
</Frame>

***

## 🔌 Part A — Add the Autoplay MCP server to Maven

Maven discovers tools from any MCP server and registers them as actions your agent can call.

<Steps>
  <Step title="Open your agent's Apps">
    In Maven AGI, open your agent, go to **Apps**, and find the **MCP** app (Browse & Install → search "MCP").
  </Step>

  <Step title="Configure the connection">
    Install the MCP app and enter:

    * **MCP URL:** `https://mcp.autoplay.ai/mcp`
    * **MCP auth token:** your **`mcp_key`** (from your product registration)
  </Step>

  <Step title="Install">
    Click **Install**. Maven connects to the server and registers the Autoplay MCP tools as actions automatically.
  </Step>
</Steps>

Maven should show these Autoplay actions under **Capabilities**:

| Tool                     | What Maven uses it for                                                                    |
| ------------------------ | ----------------------------------------------------------------------------------------- |
| `get_live_user_activity` | Reads the user's recent in-app activity so Maven can answer with live context.            |
| `get_onboarding_context` | Reads the user's current onboarding state, next step, completed steps, and stalled state. |
| `guide_next_step`        | Launches the next guided tour after the user explicitly says yes.                         |
| `list_user_tours`        | Lists available tours when the user asks to browse or pick one.                           |
| `trigger_user_tour`      | Launches a specific tour selected by the user.                                            |

<Warning>
  Install the MCP app **from inside an agent** (your agent → Apps → MCP), not from the global directory. Installing without an agent fails the post-install step.
</Warning>

<Tip>
  Tool definitions are captured **at install time**. If the tool's description ever changes, **reinstall** the MCP app so Maven picks up the update.
</Tip>

<Check>
  **Verify it now in the Simulator.** Open **Simulator** and ask: *"My product\_id is `your-product-id` and my user\_id is `a-real-user-id`. What have I done recently?"* Maven calls `get_live_user_activity` and answers with that user's activity. (In the Simulator you pass the ids in the message; Parts C and D wire identity automatically so your real users never have to.)
</Check>

***

## 🧠 Part B — Add the live-activity instructions

Open your agent in Maven AGI, go to **Settings** → **Response customization**, and paste this into **Additional persona instructions**.

Replace `<YOUR_PRODUCT_ID>` with the real `product_id` printed by your own `onboard_product` call (see [Quickstart](/quickstart)). Replace `<YOUR_APP_NAME>` with your product name.

```text theme={null}
These instructions add live-activity awareness. They govern tool use only. For identity, voice, scope, escalation, and content restrictions, follow your base persona above.

IDS (hardcoded — never ask the user for these)

product_id is ALWAYS "<YOUR_PRODUCT_ID>".
user_id comes from the session.

[AUTOPLAY LAYER 1 START] — activity-aware support

TOOL: get_live_user_activity — your live view of what this user is doing in <YOUR_APP_NAME>.

Call it at the start of every conversation, before your first substantive reply.
Re-call it whenever your next answer could depend on what the user has done, or the conversation has moved on since your last call — never reason from stale activity.
Skip it only for a pure pleasantry ("hi", "thanks") that needs no product context.
Never describe the tool call or its result. Use it only to ground your answer — reference what the user has done, not raw event data.
If it fails or returns empty, answer normally without mentioning it. [AUTOPLAY LAYER 1 END]
```

<Warning>
  Do not paste the placeholder literally. Maven should see your actual Autoplay `product_id`, while `user_id` stays session-derived through the verified identity setup below.
</Warning>

***

## 💬 Part C — Embed the Maven chat widget

This is the surface your users talk to. Maven distributes it as a **Chat** app.

<Steps>
  <Step title="Install the Chat app">
    In your agent → **Apps** → **Browse & Install** → search **"Chat"** → install the **Chat** app.
  </Step>

  <Step title="Allow your domain">
    Open the Chat app → **Settings** → **Security** → **Allowed domains** and add the domain your app runs on (e.g. `localhost` for local testing, then your production domain).
  </Step>

  <Step title="Copy your snippet">
    Open the Chat app → **Settings** → **Instructions** tab to find your snippet with your real `organizationId` and `agentId`.
  </Step>

  <Step title="Add it to your app">
    Drop the widget script into your site, just before the closing `</body>` tag:

    ```html theme={null}
    <script src="https://chat.onmaven.app/js/widget.js" defer></script>
    <script async>
      addEventListener("load", function () {
        Maven.ChatWidget.load({
          organizationId: "YOUR_ORGANIZATION_ID",
          agentId: "YOUR_AGENT_ID",
        });
      });
    </script>
    ```
  </Step>
</Steps>

<Note>
  If your site uses a **Content Security Policy**, allow `chat.onmaven.app` in your `script-src`, `connect-src`, and `frame-src` directives.
</Note>

At this point the widget loads — but Maven doesn't yet know **who** the user is. That's Part D.

***

## 🔐 Part D — Pass a verified user identity

Maven only pulls the *right* user's activity if it sends the correct `user_id` to the tool. The secure way is **signed user data**: your backend cryptographically signs the logged-in user's identity, so it can't be forged.

### 1. Configure the keys — in Maven

In the Chat app → **Settings** → **Security**, set:

* **JWT Public Key** — the public half of a signing keypair you generate (Maven uses it to verify the signature).
* **Encryption secret** — a shared secret (Maven uses it to decrypt the token).

Generate them once:

```bash theme={null}
# EC P-256 keypair (ES256) — paste the PUBLIC key into "JWT Public Key"
openssl ecparam -genkey -name prime256v1 -noout -out private.pem
openssl ec -in private.pem -pubout -out public.pem
openssl pkcs8 -topk8 -nocrypt -in private.pem -out private_pkcs8.pem  # use this on your server

# 32-byte base64url encryption secret — paste into "Encryption secret"
openssl rand 32 | base64 | tr '+/' '-_' | tr -d '='
```

<Warning>
  The **private key** and the **encryption secret** are server-side only. Never ship them to the browser or commit them.
</Warning>

### 2. Sign the user's identity — on your backend

Add an endpoint your frontend calls for the logged-in user. It **signs** the user's data (ES256), then **encrypts** the signed token (JWE):

```javascript theme={null}
// BACKEND — runs on your server, where the private key + secret are safe.
import { SignJWT, EncryptJWT, importPKCS8, base64url } from "jose";

export async function getMavenToken(user) {
  const privateKey = await importPKCS8(process.env.MAVEN_PRIVATE_KEY_PKCS8, "ES256");

  const signed = await new SignJWT({
    id: user.id, // ← the SAME id your analytics identifies the user with
    firstName: user.firstName,
    lastName: user.lastName,
    email: user.email,
  })
    .setProtectedHeader({ alg: "ES256" })
    .setIssuedAt()
    .setExpirationTime("1d")
    .sign(privateKey);

  return new EncryptJWT({ jwt: signed })
    .setProtectedHeader({ alg: "dir", enc: "A128CBC-HS256" })
    .encrypt(base64url.decode(process.env.MAVEN_ENCRYPTION_SECRET));
}
```

<Tip>
  Set **`id`** to the **same stable id your analytics identifies the user with** (the value you pass to `posthog.identify(...)` / Amplitude `setUserId(...)`). Maven fills the tool's `user_id` argument from this verified identity — so make sure `id` is your canonical user id, not just an email.
</Tip>

### 3. Hand the token to the widget — in your frontend

Fetch the token and pass it as `signedUserData`. Send your constant `product_id` as `unsignedUserData`:

```javascript theme={null}
const { token } = await fetch("/api/maven-token").then((r) => r.json());

Maven.ChatWidget.load({
  organizationId: "YOUR_ORGANIZATION_ID",
  agentId: "YOUR_AGENT_ID",
  signedUserData: token,                          // verified identity (incl. user_id)
  unsignedUserData: { product_id: "YOUR_PRODUCT_ID" },
});
```

Replace `YOUR_ORGANIZATION_ID`, `YOUR_AGENT_ID`, and `YOUR_PRODUCT_ID` with the real values from your Chat app's Instructions tab and your own `onboard_product` call — don't paste the placeholder text literally.

<Warning>
  **The single most important rule:** the `user_id` Maven sends **must equal** the id your activity is stored under — the same stable id you pass to `posthog.identify(...)` / Amplitude `setUserId(...)`. If they don't match, lookups come back empty. Pick **one** canonical user identifier and use it everywhere: your analytics `identify()`, the signed `user_id`, and the connector.
</Warning>

***

## ✅ Test it

1. Log in to your app as a user and **click around** a few pages.
2. Wait a few seconds for the events to reach the connector.
3. Open the Maven widget and ask: **"What have I done recently?"**

Maven should answer with the pages and actions that user just took.

<AccordionGroup>
  <Accordion title="Maven says there's no recent activity">
    Almost always an **identity mismatch** — the `user_id` Maven sent doesn't match the id your activity is stored under. Confirm your analytics `identify()` id, the signed `user_id` field, and the connector's stored id are all the **same** value.
  </Accordion>

  <Accordion title="The widget doesn't appear">
    Check **Allowed domains** in the Chat app settings includes your domain, and that your CSP allows `chat.onmaven.app`.
  </Accordion>

  <Accordion title="No tools appear after installing the MCP app">
    Verify the **MCP URL** and **token** are correct, and that you installed the MCP app **inside an agent**. Reinstall to re-discover tools.
  </Accordion>
</AccordionGroup>

***

Once Maven can pull a user's activity on demand, you're done with Step 1. Next: **[Step 2 — Add proactive layer](/recipes/maven/step-2-define-proactive-triggers)**.
