# List Messages — Dify

> Return a Dify Chatflow, Chatbot, Agent, or Legacy Agent conversation's message history. The first call returns the latest messages; page backward into older ones with First Message ID. Use List Conversations to find a Conversation ID. Each…

- Key: `dify-list-messages`
- Type: Action (Read-only)
- Version: 0.0.1
- App: Dify (`dify`) — https://pipedream.com/apps/dify.md
- This page (HTML): https://pipedream.com/apps/dify/actions/list-messages
- Hints: read-only · open-world
- Source: https://github.com/PipedreamHQ/pipedream/blob/master/components/dify/actions/list-messages/list-messages.mjs

## Description

Return a Dify Chatflow, Chatbot, Agent, or Legacy Agent conversation's message history. The first call returns the latest messages; page backward into older ones with `First Message ID`. Use **List Conversations** to find a `Conversation ID`. Each message includes the `query`/`answer` pair, so this is how an agent reconstructs prior turns of a conversation instead of relying on its own memory. By default each message is trimmed to `id`, `conversation_id`, `query`, `answer`, `status`, `error`, `feedback`, and `created_at`; set `Include Full Details` to also get retrieved knowledge-base passages (`retriever_resources`), agent reasoning (`agent_thoughts`), files, and token usage. Example: `Conversation ID` `45701982-8118-4bc5-8e9b-64562b4555f2`, `User` `user-123` → `{ data: [{ id, conversation_id, query: "What are the specs of the iPhone 13 Pro Max?", answer: "...", status: "normal", feedback: { rating: "like" }, created_at }], has_more: true, limit: 20 }`. If `has_more` is `true`, call again with `First Message ID` set to the `id` of the first message in `data` to get older messages. [See the documentation](https://docs.dify.ai/en/api-reference/conversations/list-conversation-messages)

## Props

| Prop | Type | Required | Description |
|---|---|---|---|
| `conversationId` | `string` | Yes | The ID of the conversation to read. Use List Conversations to find valid IDs. |
| `user` | `string` | Yes | A unique identifier for the end user, defined by you (e.g. an internal user ID or session ID) — not a Dify account. Dify scopes conversations, messages, and files to this value, so reuse the same User across requests for the same end user. When reading conversations or messages, this must match the User value used when they were created — Dify returns an empty page, not an error, for a mismatched value. For List Conversations and List Messages, Dify has no endpoint to list end users: use the User value from the user's request, or ask for it. See the documentation |
| `firstId` | `string` | No | Pagination cursor: the id of the first message in the current page's data array. Pass it to fetch the previous (older) page. Omit to fetch the latest messages. |
| `limit` | `integer` | No | Number of results to return per page, between 1 and 100. Defaults to 20. |
| `includeFullDetails` | `boolean` | No | Return Dify's full message objects, including retriever_resources, agent_thoughts, message_files, inputs, and token/price usage. These can be large on knowledge-base and agent apps. Defaults to false. |

## Run it

**MCP**

```ts
import { Client } from "@modelcontextprotocol/sdk/client/index.js"
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"
import { PipedreamClient } from "@pipedream/sdk"

const pd = new PipedreamClient({
  projectId: process.env.PIPEDREAM_PROJECT_ID!,
  clientId: process.env.PIPEDREAM_CLIENT_ID!,
  clientSecret: process.env.PIPEDREAM_CLIENT_SECRET!,
  projectEnvironment: "production",
})

const accessToken = await pd.rawAccessToken

const transport = new StreamableHTTPClientTransport(
  new URL("https://remote.mcp.pipedream.net/v3"),
  {
    requestInit: {
      headers: {
        Authorization: `Bearer ${accessToken}`,
        "x-pd-project-id": process.env.PIPEDREAM_PROJECT_ID!,
        "x-pd-environment": "production",
        "x-pd-external-user-id": "{external_user_id}", // any stable ID for this user in your system
        "x-pd-app-slug": "dify",
      },
    },
  },
)

const mcp = new Client({ name: "my-agent", version: "1.0.0" })
await mcp.connect(transport)

const { tools } = await mcp.listTools()

// listTools() hands your model this tool's input schema, so it can
// fill the arguments itself:
const result = await mcp.callTool({
  name: "dify-list-messages",
  arguments: {
    conversationId: "Conversation ID",
    user: "User",
  },
})
```

**TypeScript**

```ts
import { PipedreamClient } from "@pipedream/sdk"

const pd = new PipedreamClient({
  projectId: process.env.PIPEDREAM_PROJECT_ID!,
  clientId: process.env.PIPEDREAM_CLIENT_ID!,
  clientSecret: process.env.PIPEDREAM_CLIENT_SECRET!,
  projectEnvironment: "production",
})

const result = await pd.actions.run({
  id: "dify-list-messages",
  externalUserId: "{external_user_id}", // any stable ID for this user in your system
  configuredProps: {
    dify: { authProvisionId: "apn_xxxxxxx" },
    conversationId: "Conversation ID",
    user: "User",
  },
})

console.log(result)
```

**cURL**

```bash
curl -X POST https://api.pipedream.com/v1/connect/{project_id}/actions/run \
  -H "Content-Type: application/json" \
  -H "X-PD-Environment: production" \
  -H "Authorization: Bearer {access_token}" \
  -d '{
    "external_user_id": "{external_user_id}",
    "id": "dify-list-messages",
    "configured_props": {
      "dify": { "authProvisionId": "apn_xxxxxxx" },
      "conversationId": "Conversation ID",
      "user": "User"
    }
  }'
```

---

- App: https://pipedream.com/apps/dify.md · All apps: https://pipedream.com/apps
