Social Media Listening

Overview

This recipe demonstrates how to leverage Airtop’s SDK to autonomously search social media posts and automate a reply. We can achieve all that by using just the following API’s:

Demo

A live demo of this recipe is available here. You can sign up to create an API key for free and try it out yourself!

Running Locally

To get started, ensure you have:

  • Node.js installed on your system.
  • An Airtop API key. You can get one for free.
  1. Clone the repository and install dependencies
$git clone https://github.com/airtop-ai/examples-typescript.git
>cd examples-typescript
>pnpm i
>turbo build:packages
>cd examples/social-media-listening
>pnpm i
  1. Run the CLI. This will run the agent on the command line and is useful for quickly testing the agent.
$pnpm run cli

If you want to use the same parameters as in the example. You can run the script using the default values:

$pnpm cli --defaults
  1. (optional) Run the web application. This will start the Next.js app that is demoed in the video above.
$pnpm dev

Walkthrough

App Flowchart

The application will require you to enter a few parameters to accomplish the task.

  • Airtop Profile (Optional): If you enter a Profile Name that is already logged in to x.com, this will skip the step of having you log in.
  • Query: The query to use in X’s search bar. E.g. #ai #agents #langchain.
  • Match Prompt: The criteria to use to find candidate posts to reply to. E.g. The post mentions an AI framework or tool.
  • Reply Prompt: The way in which the reply should be written. E.g. Friendly response that casually mentions Airtop.
  • Result Limit: The number of posts to extract.

Sign in

Here the agent is prompted to verify if the user is signed in or not.

Under the Hood
1const isLoggedInPromptResponse = await this.client.windows.pageQuery(sessionId, windowId, {
2 prompt: IS_LOGGED_IN_PROMPT,
3 configuration: {
4 outputSchema: IS_LOGGED_IN_OUTPUT_SCHEMA,
5 },
6});
7const parsedResponse = JSON.parse(isLoggedInPromptResponse.data.modelResponse)
8return parsedResponse.isLoggedIn;
"This view displays either X home page or the login form. Follow the JSON schema below."

Extract posts

After the agent has validated that the user is signed in, it will proceed with finding the posts based on the query and the matchPrompt.

Under the Hood
1// Navigate to the search page
2await this.client.windows.loadUrl(sessionId, windowId, { url: `https://x.com/search?q=${encodedQuery}&f=live` });
3
4// Extract the posts
5const pageResponse = await this.client.windows.pageQuery(sessionId, windowId, {
6 prompt: extractionPrompt,
7 followPaginationLinks: true, // tell the agent to scroll down in the results page
8 configuration: {
9 outputSchema: EXTRACTED_POST_OUTPUT_SCHEMA,
10 },
11});
12const parsedResponse = JSON.parse(pageResponse.data.modelResponse || "{}") as TExtractedPostResult;
13return parsedResponse.postList;
This is the X feed. Please extract the first {REASULT_LIMIT} posts that match the criteria below, extract the URL to the post, the author's username and the post content.
Criteria: {MATCH_PROMPT}

Reply to the first matched post

The agent will generate a reply based on replyPrompt provided at the beginning. It will generate a reply only for the first matched post just to keep this recipe simple, however, this behavior could be easily adjusted to cover all the extracted posts.

Under the Hood
1// Navigate to the post
2await this.client.windows.loadUrl(sessionId, windowId, { url: postLink });
3
4// the agent will generate a reponse for the post it "sees"
5const pageResponse = await this.client.windows.pageQuery(sessionId, windowId, {
6 prompt: generateReplyPrompt,
7 configuration: {
8 outputSchema: GENERATED_REPLY_OUTPUT_SCHEMA,
9 },
10});
11
12const suggestedReply = pageResponse.data.modelResponse
This is a post in X. Please reply to the post using less than 30 words and follow the criteria below.
Criteria: {REPLY_PROMPT}