diff --git a/apps/rowboat/app/lib/prebuilt-cards/Reddit on Slack.json b/apps/rowboat/app/lib/prebuilt-cards/Reddit on Slack.json index 980c9185..e34222c6 100644 --- a/apps/rowboat/app/lib/prebuilt-cards/Reddit on Slack.json +++ b/apps/rowboat/app/lib/prebuilt-cards/Reddit on Slack.json @@ -291,7 +291,7 @@ ], "startAgent": "Reddit Post Pipeline", "lastUpdatedAt": "2025-09-09T17:48:53.292Z", - "name": "Reddit on Slack", + "name": "Browse Reddit on Slack", "description": "Browses Reddit for topics of interest and sends them to a Slack channel.", - "category": "News" + "category": "News & Social" } \ No newline at end of file diff --git a/apps/rowboat/app/lib/prebuilt-cards/Tweet with generated image.json b/apps/rowboat/app/lib/prebuilt-cards/Tweet with generated image.json new file mode 100644 index 00000000..5901c20f --- /dev/null +++ b/apps/rowboat/app/lib/prebuilt-cards/Tweet with generated image.json @@ -0,0 +1,299 @@ +{ + "agents": [ + { + "name": "Tweet Assistant", + "type": "conversation", + "description": "Assists users in creating and posting tweets with images, including crafting tweet text, generating images, and posting to Twitter.", + "instructions": "## šŸ§‘ā€šŸ’¼ Role:\nYou are a helpful assistant that helps users create and post tweets with images. You can assist with crafting the tweet text, finding information, generating images, and finally posting the tweet to Twitter.\n\n---\n## āš™ļø Operating Procedure:\n1. Greet the user and ask for the text they want to include in the tweet. Offer to help them craft it or find information about a topic.\n2. If the user asks for help with a topic, use [@tool:Composio DuckDuckGo Search](#mention) and [@tool:Exa Answer](#mention) to find relevant information and present it to the user.\n3. Once the tweet text is finalized, work with the user for description of the image they want to include in the tweet.\n4. Use [@tool:Generate Image](#mention) with the image description to generate the image.\n5. Use [@tool:Create a post](#mention) with the tweet text and the generated image (or its ID).\n6. Inform the user when the tweet has been successfully posted.\n\n---\n## šŸŽÆ Scope:\nāœ… In Scope:\n- Interacting with the user to get tweet text and image description.\n- Offering assistance in crafting tweets and finding information.\n- Generating images from text descriptions.\n- Posting tweets with images to Twitter.\n\nāŒ Out of Scope:\n- None, this agent handles the entire workflow.\n\n---\n## šŸ“‹ Guidelines:\nāœ”ļø Dos:\n- Always confirm the tweet text and image description with the user.\n- Be proactive in offering help and suggestions for tweet content.\n- Ensure the generated image matches the description.\n- Ensure the tweet text and image are correctly posted.\n\n🚫 Don'ts:\n- Do not fabricate information.\n\n", + "model": "google/gemini-2.5-flash", + "toggleAble": true, + "ragReturnType": "chunks", + "ragK": 3, + "controlType": "retain", + "outputVisibility": "user_facing", + "examples": "\n" + } + ], + "prompts": [], + "tools": [ + { + "name": "Generate Image", + "description": "Generate an image using Google Gemini given a text prompt. Returns base64-encoded image data and any text parts.", + "isGeminiImage": true, + "parameters": { + "type": "object", + "properties": { + "prompt": { + "type": "string", + "description": "Text prompt describing the image to generate" + }, + "modelName": { + "type": "string", + "description": "Optional Gemini model override" + } + }, + "required": [ + "prompt" + ], + "additionalProperties": true + } + }, + { + "name": "Create a post", + "description": "Creates a tweet on twitter; `text` is required unless `card uri`, `media media ids`, `poll options`, or `quote tweet id` is provided.", + "parameters": { + "type": "object", + "properties": { + "card_uri": { + "description": "URI of a card to attach. Mutually exclusive with `quote_tweet_id`, `poll` parameters, `media` parameters, and `direct_message_deep_link`.", + "examples": [ + "https://example.com/my-card" + ], + "title": "Card Uri", + "type": "string" + }, + "direct_message_deep_link": { + "description": "Deep link to a private Direct Message conversation. Mutually exclusive with `card_uri`.", + "examples": [ + "https://twitter.com/messages/compose?recipient_id=12345&text=Hi" + ], + "title": "Direct Message Deep Link", + "type": "string" + }, + "for_super_followers_only": { + "default": false, + "description": "Restricts Tweet visibility to the author's Super Followers.", + "examples": [ + "True", + "False" + ], + "title": "For Super Followers Only", + "type": "boolean" + }, + "geo__place__id": { + "description": "Twitter Place ID to associate with the Tweet.", + "examples": [ + "df51dec6f4ee2b2c" + ], + "title": "Geo Place Id", + "type": "string" + }, + "media__media__ids": { + "description": "Up to 4 Media IDs obtained from prior uploads. Mutually exclusive with `card_uri`.", + "examples": [ + [ + "1146032800000000000", + "1146032800000000001" + ] + ], + "items": { + "properties": {}, + "type": "string" + }, + "title": "Media Media Ids", + "type": "array" + }, + "media__tagged__user__ids": { + "description": "User IDs to tag in media; tagged users must have enabled photo tagging. Mutually exclusive with `card_uri`.", + "examples": [ + [ + "2244994945", + "783214" + ] + ], + "items": { + "properties": {}, + "type": "string" + }, + "title": "Media Tagged User Ids", + "type": "array" + }, + "nullcast": { + "default": false, + "description": "Marks the Tweet as a promoted-only post, not appearing in public timelines or served to followers.", + "examples": [ + "True", + "False" + ], + "title": "Nullcast", + "type": "boolean" + }, + "poll__duration__minutes": { + "description": "Poll duration in minutes (5-10080). Required if `poll_options` are provided. Mutually exclusive with `card_uri`.", + "examples": [ + "60", + "1440", + "10080" + ], + "title": "Poll Duration Minutes", + "type": "integer" + }, + "poll__options": { + "description": "List of 2 to 4 poll options (max 25 characters each). Required if creating a poll. Mutually exclusive with `card_uri`.", + "examples": [ + [ + "Yes", + "No" + ], + [ + "Option A", + "Option B", + "Option C" + ] + ], + "items": { + "properties": {}, + "type": "string" + }, + "title": "Poll Options", + "type": "array" + }, + "poll__reply__settings": { + "description": "Specifies who can reply to the poll Tweet: 'following' or 'mentionedUsers'. Mutually exclusive with `card_uri`.", + "enum": [ + "following", + "mentionedUsers" + ], + "examples": [ + "following", + "mentionedUsers" + ], + "title": "Poll Reply Settings", + "type": "string" + }, + "quote_tweet_id": { + "description": "ID of the Tweet to quote. Mutually exclusive with `card_uri`, `poll` parameters, and `direct_message_deep_link`.", + "examples": [ + "1346889436626259968" + ], + "pattern": "^[0-9]{1,19}$", + "title": "Quote Tweet Id", + "type": "string" + }, + "reply__exclude__reply__user__ids": { + "description": "User IDs to exclude from @mentioning in the reply; these users will not be notified. Used when `reply_in_reply_to_tweet_id` is set.", + "examples": [ + [ + "123456789", + "987654321" + ] + ], + "items": { + "properties": {}, + "type": "string" + }, + "title": "Reply Exclude Reply User Ids", + "type": "array" + }, + "reply__in__reply__to__tweet__id": { + "description": "ID of the Tweet to which this is a reply. Required if creating a reply.", + "examples": [ + "1346889436626259960" + ], + "pattern": "^[0-9]{1,19}$", + "title": "Reply In Reply To Tweet Id", + "type": "string" + }, + "reply_settings": { + "description": "Specifies who can reply to this Tweet: 'following', 'mentionedUsers', or 'subscribers' (X Premium subscribers).", + "enum": [ + "following", + "mentionedUsers", + "subscribers" + ], + "examples": [ + "following", + "mentionedUsers", + "subscribers" + ], + "title": "Reply Settings", + "type": "string" + }, + "text": { + "description": "Text content of the Tweet (max 280 characters). Required unless `card_uri`, `media_media_ids`, `poll_options`, or `quote_tweet_id` are provided.", + "examples": [ + "Hello world!", + "Check out this cool new feature! #innovation" + ], + "title": "Text", + "type": "string" + } + }, + "required": [] + }, + "mockTool": false, + "isComposio": true, + "composioData": { + "slug": "TWITTER_CREATION_OF_A_POST", + "noAuth": false, + "toolkitName": "twitter", + "toolkitSlug": "twitter", + "logo": "https://cdn.jsdelivr.net/gh/ComposioHQ/open-logos@master/twitter.png" + } + }, + { + "name": "Exa Answer", + "description": "Get answers with citations using the exa api.", + "parameters": { + "type": "object", + "properties": { + "content": { + "description": "The user message content for the Exa answer API.", + "examples": [ + "give me image of narendra modi" + ], + "title": "Content", + "type": "string" + } + }, + "required": [ + "content" + ] + }, + "mockTool": false, + "isComposio": true, + "composioData": { + "slug": "COMPOSIO_SEARCH_EXA_ANSWER", + "noAuth": true, + "toolkitName": "composio_search", + "toolkitSlug": "composio_search", + "logo": "https://cdn.jsdelivr.net/gh/ComposioHQ/open-logos@master//composio-logo.png" + } + }, + { + "name": "Composio DuckDuckGo Search", + "description": "The duckduckgosearch class utilizes the composio duckduckgo search api to perform searches, focusing on web information and details. it leverages the duckduckgo search engine via the composio duckduckgo search api to retrieve relevant web data based on the provided query.", + "parameters": { + "type": "object", + "properties": { + "query": { + "description": "The search query for the Composio DuckDuckGo Search API, specifying the search topic.", + "examples": [ + "Python programming" + ], + "title": "Query", + "type": "string" + } + }, + "required": [ + "query" + ] + }, + "mockTool": false, + "isComposio": true, + "composioData": { + "slug": "COMPOSIO_SEARCH_DUCK_DUCK_GO_SEARCH", + "noAuth": true, + "toolkitName": "Composio search", + "toolkitSlug": "composio_search", + "logo": "https://cdn.jsdelivr.net/gh/ComposioHQ/open-logos@master//composio-logo.png" + } + } + ], + "pipelines": [], + "startAgent": "Tweet Assistant", + "lastUpdatedAt": "2025-09-11T18:02:35.880Z", + "name": "Viral Tweet Assistant", + "description": "Research topics and create a tweet including generated images.", + "category": "News & Social" +} \ No newline at end of file diff --git a/apps/rowboat/app/lib/prebuilt-cards/customer-support.json b/apps/rowboat/app/lib/prebuilt-cards/customer-support.json new file mode 100644 index 00000000..6c117344 --- /dev/null +++ b/apps/rowboat/app/lib/prebuilt-cards/customer-support.json @@ -0,0 +1,112 @@ +{ + "agents": [ + { + "name": "Product & Delivery Assistant", + "type": "conversation", + "description": "Hub agent to answer product information questions (using RAG) and delivery status questions.", + "instructions": "## šŸ§‘ā€šŸ’¼ Role:\nYou are the hub agent responsible for orchestrating responses to product information and delivery status questions.\n\n---\n## āš™ļø Steps to Follow:\n1. Greet the user and ask how you can help. Say something like 'Hi, I'm [@variable:Assistant name](#mention) from [@variable:Company name](#mention). How can I help you today?'\n2. Determine if the user's question is about product information or delivery status.\n3. If the question is about product information, transfer to [@agent:Product Information Agent](#mention).\n4. If the question is about delivery status, transfer to [@agent:Delivery Status Agent](#mention).\n5. If the question is neither, politely inform the user that you can only help with product information or delivery status.\n6. Return the final answer to the user.\n\n---\n## šŸŽÆ Scope:\nāœ… In Scope:\n- Routing product information questions.\n- Routing delivery status questions.\n\nāŒ Out of Scope:\n- Directly answering product or delivery questions.\n- Handling questions outside of product information or delivery status.\n\n---\n## šŸ“‹ Guidelines:\nāœ”ļø Dos:\n- Clearly identify the type of user query.\n- Route to the correct agent.\n\n🚫 Don'ts:\n- Do not attempt to answer questions directly.\n- Do not ask for personal information unless explicitly required by a sub-agent.\n- CRITICAL: Only transfer to one agent at a time and wait for its response before proceeding.\n\n", + "examples": "- **User** : What are the features of product X?\n - **Agent actions**: Call [@agent:Product Information Agent](#mention)\n\n- **User** : Where is my order?\n - **Agent actions**: Call [@agent:Delivery Status Agent](#mention)\n\n- **User** : How do I reset my password?\n - **Agent response**: I can only help with product information or delivery status questions. How else can I assist you today?", + "model": "gpt-4o", + "toggleAble": true, + "ragReturnType": "chunks", + "ragK": 3, + "outputVisibility": "user_facing", + "controlType": "retain" + }, + { + "name": "Product Information Agent", + "type": "conversation", + "description": "Answers product information questions using RAG data sources.", + "disabled": false, + "instructions": "## šŸ§‘ā€šŸ’¼ Role:\nYou are an internal agent that answers product information questions using RAG data sources. If you receive a question that is not about product information, you must return control to the parent agent with a message indicating the question is out of your scope.\n\n---\n## āš™ļø Steps to Follow:\n1. Receive the product information question from the parent agent.\n2. Determine if the question is about product information.\n - If yes: Use RAG search to pull information from the available data sources to answer the question.\n - If not: Return control to the parent agent with a message such as \"This question is not about product information. Returning to parent agent.\"\n3. Formulate a clear and concise answer based on the RAG results (if applicable).\n4. If question is out of scope call [@agent:Product & Delivery Assistant](#mention) \n\n---\n## šŸŽÆ Scope:\nāœ… In Scope:\n- Answering product information questions using RAG.\n- Returning control to parent if the question is out of scope.\n\nāŒ Out of Scope:\n- Handling delivery status questions.\n- Interacting directly with the user.\n\n---\n## šŸ“‹ Guidelines:\nāœ”ļø Dos:\n- Use RAG search to find relevant information for product questions.\n- If the question is not about product information, return control to the parent agent with a clear message.\n\n🚫 Don'ts:\n- Do not answer questions outside of product information.\n- Do not interact with the user directly.\n- Do not ignore out-of-scope questions; always return to parent.\n", + "examples": "\n", + "model": "gpt-4o", + "locked": false, + "toggleAble": true, + "ragDataSources": [ + "68c3172a72d2a6bd1c4a2afe" + ], + "ragReturnType": "chunks", + "ragK": 3, + "outputVisibility": "user_facing", + "controlType": "retain", + "maxCallsPerParentAgent": 3 + }, + { + "name": "Delivery Status Agent", + "type": "conversation", + "description": "Answers delivery status questions using the Exa Answer tool.", + "disabled": false, + "instructions": "## šŸ§‘ā€šŸ’¼ Role:\nYou are an internal agent that answers delivery status questions. If you receive a question that is not about delivery status, you must return control to the parent agent with a message indicating the question is out of your scope.\n\n---\n## āš™ļø Steps to Follow:\n1. Receive the delivery status question from the parent agent.\n2. Determine if the question is about delivery status.\n - If yes: Use the [@tool:Mock Delivery Status](#mention) tool to search for delivery status information. You may need to ask the user for an order number or tracking ID if not provided.\n - If not: Return control to the parent agent with a message such as \"This question is not about delivery status. Returning to parent agent.\"\n3. Formulate a clear and concise answer based on the tool's results (if applicable).\n4. If question is out of scope call [@agent:Product & Delivery Assistant](#mention) \n---\n## šŸŽÆ Scope:\nāœ… In Scope:\n- Answering delivery status questions using the Exa Answer tool.\n- Returning control to parent if the question is out of scope.\n\nāŒ Out of Scope:\n- Handling product information questions.\n- Interacting directly with the user (except to ask for necessary information like order ID).\n\n---\n## šŸ“‹ Guidelines:\nāœ”ļø Dos:\n- Use the Exa Answer tool to find delivery information for delivery status questions.\n- If the question is not about delivery status, return control to the parent agent with a clear message.\n- Ask for order details if needed.\n\n🚫 Don'ts:\n- Do not answer questions outside of delivery status.\n- Do not interact with the user directly unless absolutely necessary to get information for the tool.\n- Do not ignore out-of-scope questions; always return to parent.\n", + "examples": "\n", + "model": "gpt-4o", + "locked": false, + "toggleAble": true, + "ragReturnType": "chunks", + "ragK": 3, + "outputVisibility": "user_facing", + "controlType": "retain", + "maxCallsPerParentAgent": 3 + } + ], + "prompts": [ + { + "name": "Company name", + "type": "base_prompt", + "prompt": "" + }, + { + "name": "Assistant name", + "type": "base_prompt", + "prompt": "" + } + ], + "tools": [ + { + "name": "Generate Image", + "description": "Generate an image using Google Gemini given a text prompt. Returns base64-encoded image data and any text parts.", + "parameters": { + "type": "object", + "properties": { + "prompt": { + "type": "string", + "description": "Text prompt describing the image to generate" + }, + "modelName": { + "type": "string", + "description": "Optional Gemini model override" + } + }, + "required": [ + "prompt" + ], + "additionalProperties": true + }, + "isGeminiImage": true + }, + { + "name": "Mock Delivery Status", + "description": "A mock tool to simulate checking delivery status.", + "mockTool": true, + "mockInstructions": "This tool simulates checking the delivery status of an order. It will always return a predefined delivery status message.", + "parameters": { + "type": "object", + "properties": { + "order_id": { + "type": "string", + "description": "The order ID to check the delivery status for." + } + }, + "required": [ + "order_id" + ] + } + } + ], + "pipelines": [], + "startAgent": "Product & Delivery Assistant", + "lastUpdatedAt": "2025-09-11T18:51:15.548Z", + "name": "Customer Support", + "description": "Answers product information (RAG) and delivery status (MCP) questions.", + "category": "Customer Support" +} \ No newline at end of file diff --git a/apps/rowboat/app/lib/prebuilt-cards/index.ts b/apps/rowboat/app/lib/prebuilt-cards/index.ts index 2faad012..b8080c80 100644 --- a/apps/rowboat/app/lib/prebuilt-cards/index.ts +++ b/apps/rowboat/app/lib/prebuilt-cards/index.ts @@ -5,6 +5,9 @@ import githubDataToSpreadsheet from './github-data-to-spreadsheet.json'; import interviewScheduler from './interview-scheduler.json'; import meetingPrepAssistant from './Meeting Prep Assistant.json'; import redditOnSlack from './Reddit on Slack.json'; +import twitterSentiment from './twitter-sentiment.json'; +import tweetWithGeneratedImage from './Tweet with generated image.json'; +import customerSupport from './customer-support.json'; // Keep keys consistent with prior file basenames to avoid breaking links. export const prebuiltTemplates = { @@ -12,5 +15,8 @@ export const prebuiltTemplates = { 'interview-scheduler': interviewScheduler, 'Meeting Prep Assistant': meetingPrepAssistant, 'Reddit on Slack': redditOnSlack, + 'Twitter Sentiment': twitterSentiment, + 'Tweet with generated image': tweetWithGeneratedImage, + 'Customer Support': customerSupport, }; diff --git a/apps/rowboat/app/lib/prebuilt-cards/twitter-sentiment.json b/apps/rowboat/app/lib/prebuilt-cards/twitter-sentiment.json new file mode 100644 index 00000000..03f78daa --- /dev/null +++ b/apps/rowboat/app/lib/prebuilt-cards/twitter-sentiment.json @@ -0,0 +1,379 @@ +{ + "agents": [ + { + "name": "Twitter Search Agent", + "type": "pipeline", + "description": "Searches Twitter for tweets about a specified keywords.", + "disabled": false, + "instructions": "## šŸ§‘ā€šŸ’¼ Role:\nSearch Twitter for tweets about a given keyword within a specified time window.\n\n---\n## āš™ļø Steps to Follow:\n1. Receive the keywords, `start_time`, and `end_time` from the parent agent.\n2. Use the [@tool:Search full archive of tweets](#mention) tool with each keyword as the query, and the provided `start_time` and `end_time`.\n3. Return the text of the tweets to the next agent in the pipeline.\n\n---\n## šŸŽÆ Scope:\nāœ… In Scope:\n- Searching Twitter for tweets within a given time period.\n\nāŒ Out of Scope:\n- Analyzing sentiment.\n- Interacting with the user directly.\n\n---\n## šŸ“‹ Guidelines:\nāœ”ļø Dos:\n- Return only the tweet text.\n- Ensure `start_time` and `end_time` are correctly passed to the tool.\n\n🚫 Don'ts:\n- Do not perform sentiment analysis.\n- Do not interact with the user directly.", + "model": "google/gemini-2.5-flash", + "locked": false, + "toggleAble": true, + "ragReturnType": "chunks", + "ragK": 3, + "outputVisibility": "internal", + "controlType": "relinquish_to_parent", + "maxCallsPerParentAgent": 3 + }, + { + "name": "Sentiment Analysis Agent", + "type": "pipeline", + "description": "Analyzes the sentiment of tweets and provides a positive sentiment score for each.", + "disabled": false, + "instructions": "## šŸ§‘ā€šŸ’¼ Role:\nAnalyze the sentiment of tweets and provide a positive sentiment score for each.\n\n---\n## āš™ļø Steps to Follow:\n1. Receive a list of tweets from the previous agent in the pipeline.\n2. For each tweet, classify its sentiment into positive, negative, or neutral.\n3. Return a list of tweets with their corresponding positive sentiment score.\n\n---\n## šŸŽÆ Scope:\nāœ… In Scope:\n- Analyzing tweet sentiment.\n- Providing a positive sentiment score.\n\nāŒ Out of Scope:\n- Searching Twitter.\n- Interacting with the user directly.\n\n---\n## šŸ“‹ Guidelines:\nāœ”ļø Dos:\n- Provide a clear positive sentiment score for each tweet.\n\n🚫 Don'ts:\n- Do not search Twitter.\n- Do not interact with the user directly.", + "model": "google/gemini-2.5-flash", + "locked": false, + "toggleAble": true, + "ragReturnType": "chunks", + "ragK": 3, + "outputVisibility": "internal", + "controlType": "relinquish_to_parent", + "maxCallsPerParentAgent": 3 + }, + { + "name": "Sentiment Summary Agent", + "type": "pipeline", + "description": "Summarizes the sentiment of tweets in three sentences.", + "disabled": false, + "instructions": "## šŸ§‘ā€šŸ’¼ Role:\nSummarize the sentiment of tweets.\n\n---\n## āš™ļø Steps to Follow:\n1. Receive a list of tweets with their positive sentiment scores from the previous agent.\n2. Calculate the percentage of positive tweets.\n3. Summarize the findings in three sentences, including:\n - The percentage of positive tweets.\n - General themes of positive comments.\n - General themes of negative comments.\n4. Return the summary to the parent agent.\n\n---\n## šŸŽÆ Scope:\nāœ… In Scope:\n- Summarizing tweet sentiments.\n\nāŒ Out of Scope:\n- Searching Twitter.\n- Analyzing sentiment.\n- Interacting with the user directly.\n\n---\n## šŸ“‹ Guidelines:\nāœ”ļø Dos:\n- Provide a concise summary as requested.\n\n🚫 Don'ts:\n- Do not perform other tasks.\n- Do not interact with the user directly.", + "model": "google/gemini-2.5-flash", + "locked": false, + "toggleAble": true, + "ragReturnType": "chunks", + "ragK": 3, + "controlType": "relinquish_to_parent", + "outputVisibility": "internal", + "maxCallsPerParentAgent": 3 + } + ], + "prompts": [ + { + "name": "Keyword", + "type": "base_prompt", + "prompt": "" + }, + { + "name": "LookbackInHours", + "type": "base_prompt", + "prompt": "" + } + ], + "tools": [ + { + "name": "Search full archive of tweets", + "description": "Searches the full archive of public tweets from march 2006 onwards; use 'start time' and 'end time' together for a defined time window.", + "mockTool": true, + "parameters": { + "type": "object", + "properties": { + "end_time": { + "description": "The newest UTC timestamp (YYYY-MM-DDTHH:mm:ssZ) to which Tweets will be provided. Exclusive. Example: '2021-01-31T23:59:59Z'.", + "examples": [ + "2022-11-30T23:59:59Z" + ], + "title": "End Time", + "type": "string" + }, + "expansions": { + "description": "Specifies which objects to expand in the response for more details.", + "examples": [ + [ + "author_id", + "referenced_tweets.id" + ] + ], + "items": { + "enum": [ + "article.cover_media", + "article.media_entities", + "attachments.media_keys", + "attachments.media_source_tweet", + "attachments.poll_ids", + "author_id", + "author_screen_name", + "edit_history_tweet_ids", + "entities.mentions.username", + "entities.note.mentions.username", + "geo.place_id", + "in_reply_to_user_id", + "referenced_tweets.id", + "referenced_tweets.id.author_id" + ], + "properties": {}, + "title": "ExpansionsEnm0", + "type": "string" + }, + "title": "Expansions", + "type": "array" + }, + "max_results": { + "default": 10, + "description": "The maximum number of search results to return per request. Values can be between 10 and the limit defined by the API (typically 100 or 500).", + "examples": [ + 100 + ], + "title": "Max Results", + "type": "integer" + }, + "media__fields": { + "description": "Specifies which media fields to include if 'attachments.media_keys' is expanded.", + "examples": [ + [ + "url", + "preview_image_url", + "public_metrics" + ] + ], + "items": { + "enum": [ + "alt_text", + "duration_ms", + "height", + "media_key", + "non_public_metrics", + "organic_metrics", + "preview_image_url", + "promoted_metrics", + "public_metrics", + "type", + "url", + "variants", + "width" + ], + "properties": {}, + "title": "MediaFieldsEnm0", + "type": "string" + }, + "title": "Media Fields", + "type": "array" + }, + "next_token": { + "description": "A token obtained from a previous response to retrieve the next page of results. Do not modify this value.", + "examples": [ + "7140dibdnow9c7btw423vh951v5cnqf09hyssx3h" + ], + "title": "Next Token", + "type": "string" + }, + "pagination_token": { + "description": "Alternative to 'next_token' for paginating through results. Token from a previous response for the next page. Do not modify.", + "examples": [ + "7140dibdnow9c7btw423vh951v5cnqf09hyssx3h" + ], + "title": "Pagination Token", + "type": "string" + }, + "place__fields": { + "description": "Specifies which place fields to include if 'geo.place_id' is expanded.", + "examples": [ + [ + "full_name", + "country", + "geo" + ] + ], + "items": { + "enum": [ + "contained_within", + "country", + "country_code", + "full_name", + "geo", + "id", + "name", + "place_type" + ], + "properties": {}, + "title": "PlaceFieldsEnm0", + "type": "string" + }, + "title": "Place Fields", + "type": "array" + }, + "poll__fields": { + "description": "Specifies which poll fields to include if 'attachments.poll_ids' is expanded.", + "examples": [ + [ + "duration_minutes", + "options", + "end_datetime" + ] + ], + "items": { + "enum": [ + "duration_minutes", + "end_datetime", + "id", + "options", + "voting_status" + ], + "properties": {}, + "title": "PollFieldsEnm0", + "type": "string" + }, + "title": "Poll Fields", + "type": "array" + }, + "query": { + "description": "The search query or rule to match Tweets. Maximum length varies; refer to Twitter API documentation for details (e.g., https://t.co/rulelength).", + "examples": [ + "#twitterdev OR @twitterdev", + "from:twitterdev -is:retweet" + ], + "title": "Query", + "type": "string" + }, + "since_id": { + "description": "Returns results with a Tweet ID numerically greater (more recent) than the specified ID.", + "examples": [ + "1346889436626259968" + ], + "title": "Since Id", + "type": "string" + }, + "sort_order": { + "description": "Specifies the order in which to return results. 'recency' returns the most recent Tweets first, 'relevancy' returns Tweets based on relevance.", + "enum": [ + "recency", + "relevancy" + ], + "examples": [ + "recency" + ], + "title": "Sort Order", + "type": "string" + }, + "start_time": { + "description": "The oldest UTC timestamp (YYYY-MM-DDTHH:mm:ssZ) from which Tweets will be provided. Inclusive. Example: '2021-01-01T00:00:00Z'.", + "examples": [ + "2022-11-01T00:00:00Z" + ], + "title": "Start Time", + "type": "string" + }, + "tweet__fields": { + "description": "Specifies which Tweet fields to include in the response.", + "examples": [ + [ + "created_at", + "text", + "public_metrics" + ] + ], + "items": { + "enum": [ + "article", + "attachments", + "author_id", + "card_uri", + "context_annotations", + "conversation_id", + "created_at", + "edit_controls", + "edit_history_tweet_ids", + "entities", + "geo", + "id", + "in_reply_to_user_id", + "lang", + "non_public_metrics", + "note_tweet", + "organic_metrics", + "possibly_sensitive", + "promoted_metrics", + "public_metrics", + "referenced_tweets", + "reply_settings", + "scopes", + "source", + "text", + "username", + "withheld" + ], + "properties": {}, + "title": "TweetFieldsEnm0", + "type": "string" + }, + "title": "Tweet Fields", + "type": "array" + }, + "until_id": { + "description": "Returns results with a Tweet ID numerically less (older) than the specified ID.", + "examples": [ + "1460323737035677698" + ], + "title": "Until Id", + "type": "string" + }, + "user__fields": { + "description": "Specifies which user fields to include if 'author_id' or other user-related expansions are used.", + "examples": [ + [ + "username", + "public_metrics", + "profile_image_url" + ] + ], + "items": { + "enum": [ + "affiliation", + "connection_status", + "created_at", + "description", + "entities", + "id", + "location", + "most_recent_tweet_id", + "name", + "pinned_tweet_id", + "profile_banner_url", + "profile_image_url", + "protected", + "public_metrics", + "receives_your_dm", + "subscription_type", + "url", + "username", + "verified", + "verified_type", + "withheld" + ], + "properties": {}, + "title": "UserFieldsEnm0", + "type": "string" + }, + "title": "User Fields", + "type": "array" + } + }, + "required": [ + "query" + ] + }, + "isComposio": true, + "composioData": { + "slug": "TWITTER_FULL_ARCHIVE_SEARCH", + "noAuth": false, + "toolkitName": "Twitter", + "toolkitSlug": "twitter", + "logo": "https://cdn.jsdelivr.net/gh/ComposioHQ/open-logos@master/twitter.png" + } + } + ], + "pipelines": [ + { + "name": "Twitter Sentiment Pipeline", + "description": "Searches Twitter for tweets about a company and analyzes their sentiment.", + "agents": [ + "Twitter Search Agent", + "Sentiment Analysis Agent", + "Sentiment Summary Agent" + ] + } + ], + "startAgent": "Twitter Sentiment Pipeline", + "lastUpdatedAt": "2025-09-11T17:26:48.865Z", + "name": "Twitter Sentiment", + "description": "Searches Twitter for tweets about a company and analyzes their sentiment.", + "category": "News & Social" +} \ No newline at end of file diff --git a/apps/rowboat/app/projects/components/build-assistant-section.tsx b/apps/rowboat/app/projects/components/build-assistant-section.tsx index 3b2f8196..4d711da4 100644 --- a/apps/rowboat/app/projects/components/build-assistant-section.tsx +++ b/apps/rowboat/app/projects/components/build-assistant-section.tsx @@ -471,6 +471,9 @@ export function BuildAssistantSection() {

Prebuilt Assistants

+

+ Start quickly and let Skipper adapt it to your needs. +

{templatesLoading ? (
@@ -488,7 +491,8 @@ export function BuildAssistantSection() { (() => { const workTemplates = templates.filter((t) => (t.category || '').toLowerCase() === 'work productivity'); const devTemplates = templates.filter((t) => (t.category || '').toLowerCase() === 'developer productivity'); - const newsTemplates = templates.filter((t) => (t.category || '').toLowerCase() === 'news'); + const newsTemplates = templates.filter((t) => (t.category || '').toLowerCase() === 'news & social'); + const customerSupportTemplates = templates.filter((t) => (t.category || '').toLowerCase() === 'customer support'); const renderGrid = (items: any[]) => (
@@ -582,12 +586,22 @@ export function BuildAssistantSection() {
- News + News & Social
{renderGrid(newsTemplates)}
)} + {customerSupportTemplates.length > 0 && ( +
+
+ + Customer Support + +
+ {renderGrid(customerSupportTemplates)} +
+ )}
); })()