mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-06-06 19:35:44 +02:00
Add trigger context to copilot
feat: Enhance trigger management in Copilot - Added functionality to search for relevant external triggers using the new `search_relevant_triggers` tool, allowing users to discover available triggers based on toolkit slugs and optional query keywords. - Updated the Copilot context to include detailed descriptions of various external trigger toolkits, enhancing user guidance for trigger creation. - Improved the overall trigger handling process, ensuring that users can effectively integrate external triggers into their workflows. This update significantly enhances the Copilot's capabilities in managing and utilizing external triggers.
This commit is contained in:
parent
e2c8d0490a
commit
885a7f3753
2 changed files with 167 additions and 4 deletions
|
|
@ -10,7 +10,7 @@ import { COPILOT_INSTRUCTIONS_MULTI_AGENT_WITH_DOCS as COPILOT_INSTRUCTIONS_MULT
|
||||||
import { COPILOT_MULTI_AGENT_EXAMPLE_1 } from "./example_multi_agent_1";
|
import { COPILOT_MULTI_AGENT_EXAMPLE_1 } from "./example_multi_agent_1";
|
||||||
import { CURRENT_WORKFLOW_PROMPT } from "./current_workflow";
|
import { CURRENT_WORKFLOW_PROMPT } from "./current_workflow";
|
||||||
import { USE_COMPOSIO_TOOLS } from "@/app/lib/feature_flags";
|
import { USE_COMPOSIO_TOOLS } from "@/app/lib/feature_flags";
|
||||||
import { composio, getTool } from "../composio/composio";
|
import { composio, getTool, listTriggersTypes } from "../composio/composio";
|
||||||
import { UsageTracker } from "@/app/lib/billing";
|
import { UsageTracker } from "@/app/lib/billing";
|
||||||
import { CopilotStreamEvent } from "@/src/entities/models/copilot";
|
import { CopilotStreamEvent } from "@/src/entities/models/copilot";
|
||||||
|
|
||||||
|
|
@ -228,6 +228,111 @@ async function searchRelevantTools(usageTracker: UsageTracker, query: string): P
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function searchRelevantTriggers(
|
||||||
|
usageTracker: UsageTracker,
|
||||||
|
toolkitSlug: string,
|
||||||
|
query?: string,
|
||||||
|
): Promise<string> {
|
||||||
|
const logger = new PrefixLogger("copilot-search-triggers");
|
||||||
|
const trimmedSlug = toolkitSlug.trim();
|
||||||
|
const trimmedQuery = query?.trim() || '';
|
||||||
|
console.log("🔧 TOOL CALL: searchRelevantTriggers", { toolkitSlug: trimmedSlug, query: trimmedQuery });
|
||||||
|
|
||||||
|
if (!trimmedSlug) {
|
||||||
|
logger.log('no toolkit slug provided');
|
||||||
|
return 'Please provide a toolkit slug (for example "gmail" or "slack") when searching for triggers.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!USE_COMPOSIO_TOOLS) {
|
||||||
|
logger.log('dynamic trigger search is disabled');
|
||||||
|
console.log("❌ TOOL CALL SKIPPED: searchRelevantTriggers - Composio tools disabled");
|
||||||
|
return 'Trigger search is currently unavailable.';
|
||||||
|
}
|
||||||
|
|
||||||
|
const MAX_PAGES = 5;
|
||||||
|
type TriggerListResponse = Awaited<ReturnType<typeof listTriggersTypes>>;
|
||||||
|
type TriggerType = TriggerListResponse['items'][number];
|
||||||
|
|
||||||
|
const triggers: TriggerType[] = [];
|
||||||
|
let cursor: string | undefined;
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (let page = 0; page < MAX_PAGES; page++) {
|
||||||
|
logger.log(`fetching trigger page ${page + 1} for toolkit ${trimmedSlug}`);
|
||||||
|
console.log("🔍 TOOL CALL: COMPOSIO_LIST_TRIGGERS", { toolkitSlug: trimmedSlug, cursor });
|
||||||
|
const response = await listTriggersTypes(trimmedSlug, cursor);
|
||||||
|
triggers.push(...response.items);
|
||||||
|
console.log("✅ TOOL CALL SUCCESS: COMPOSIO_LIST_TRIGGERS", {
|
||||||
|
toolkitSlug: trimmedSlug,
|
||||||
|
fetchedCount: response.items.length,
|
||||||
|
totalCollected: triggers.length,
|
||||||
|
hasNext: Boolean(response.next_cursor),
|
||||||
|
});
|
||||||
|
if (!response.next_cursor) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cursor = response.next_cursor || undefined;
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
logger.log(`trigger search failed: ${error?.message || error}`);
|
||||||
|
console.log("❌ TOOL CALL FAILED: COMPOSIO_LIST_TRIGGERS", {
|
||||||
|
toolkitSlug: trimmedSlug,
|
||||||
|
error: error?.message || error,
|
||||||
|
});
|
||||||
|
return `Trigger search failed for toolkit "${trimmedSlug}".`;
|
||||||
|
}
|
||||||
|
|
||||||
|
usageTracker.track({
|
||||||
|
type: "COMPOSIO_TOOL_USAGE",
|
||||||
|
toolSlug: `COMPOSIO_LIST_TRIGGER_TYPES:${trimmedSlug}`,
|
||||||
|
context: "copilot.search_relevant_triggers",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!triggers.length) {
|
||||||
|
logger.log('no triggers found for toolkit');
|
||||||
|
return `No triggers are currently available for toolkit "${trimmedSlug}".`;
|
||||||
|
}
|
||||||
|
|
||||||
|
let filteredTriggers = triggers;
|
||||||
|
if (trimmedQuery) {
|
||||||
|
const queryLc = trimmedQuery.toLowerCase();
|
||||||
|
filteredTriggers = triggers.filter(trigger => {
|
||||||
|
const baseText = `${trigger.name} ${trigger.slug} ${trigger.description}`.toLowerCase();
|
||||||
|
const propertyNames = Object.keys(trigger.config?.properties || {}).join(' ').toLowerCase();
|
||||||
|
return baseText.includes(queryLc) || propertyNames.includes(queryLc);
|
||||||
|
});
|
||||||
|
logger.log(`filtered triggers to ${filteredTriggers.length} results using query`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!filteredTriggers.length) {
|
||||||
|
return `No triggers found for toolkit "${trimmedSlug}"${trimmedQuery ? ` matching "${trimmedQuery}"` : ''}.`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MAX_RESULTS = 8;
|
||||||
|
const limitedTriggers = filteredTriggers.slice(0, MAX_RESULTS);
|
||||||
|
const truncated = filteredTriggers.length > limitedTriggers.length;
|
||||||
|
|
||||||
|
const formattedTriggers = limitedTriggers.map(trigger => {
|
||||||
|
const requiredFields = trigger.config.required && trigger.config.required.length
|
||||||
|
? trigger.config.required.join(', ')
|
||||||
|
: 'None';
|
||||||
|
const configJson = JSON.stringify(trigger.config, null, 2);
|
||||||
|
return `**${trigger.name}** (slug: ${trigger.slug})\nToolkit: ${trigger.toolkit.name} (${trigger.toolkit.slug})\nDescription: ${trigger.description}\nRequired config fields: ${requiredFields}\n\`\`\`json\n${configJson}\n\`\`\``;
|
||||||
|
}).join('\n\n');
|
||||||
|
|
||||||
|
const header = trimmedQuery
|
||||||
|
? `The following triggers match "${trimmedQuery}" in toolkit "${trimmedSlug}":`
|
||||||
|
: `Available triggers for toolkit "${trimmedSlug}":`;
|
||||||
|
|
||||||
|
const note = truncated
|
||||||
|
? `\n\nOnly showing the first ${MAX_RESULTS} results out of ${filteredTriggers.length}. Refine your query for more specific results.`
|
||||||
|
: '';
|
||||||
|
|
||||||
|
const response = `${header}\n\n${formattedTriggers}${note}`;
|
||||||
|
logger.log('returning trigger search response');
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
function updateLastUserMessage(
|
function updateLastUserMessage(
|
||||||
messages: z.infer<typeof CopilotMessage>[],
|
messages: z.infer<typeof CopilotMessage>[],
|
||||||
currentWorkflowPrompt: string,
|
currentWorkflowPrompt: string,
|
||||||
|
|
@ -343,7 +448,7 @@ export async function* streamMultiAgentResponse(
|
||||||
console.log("🤖 AI MODEL CALL STARTED", {
|
console.log("🤖 AI MODEL CALL STARTED", {
|
||||||
model: COPILOT_MODEL,
|
model: COPILOT_MODEL,
|
||||||
maxSteps: 20,
|
maxSteps: 20,
|
||||||
availableTools: ["search_relevant_tools"]
|
availableTools: ["search_relevant_tools", "search_relevant_triggers"]
|
||||||
});
|
});
|
||||||
|
|
||||||
const { fullStream } = streamText({
|
const { fullStream } = streamText({
|
||||||
|
|
@ -365,6 +470,23 @@ export async function* streamMultiAgentResponse(
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
"search_relevant_triggers": tool({
|
||||||
|
description: "Use this tool to discover external triggers provided by Composio toolkits. Supply the toolkit slug (for example 'gmail', 'slack', or 'salesforce') and optionally keywords from the user's request to narrow down results. Always call this before adding an external trigger to ensure the trigger exists and to understand its configuration schema.",
|
||||||
|
parameters: z.object({
|
||||||
|
toolkitSlug: z.string().describe("Slug of the Composio toolkit to search, such as 'gmail', 'slack', 'salesforce', 'googlecalendar'."),
|
||||||
|
query: z.string().min(1).describe("Optional keywords pulled from the user's request to filter trigger names, descriptions, or config fields.").optional(),
|
||||||
|
}),
|
||||||
|
execute: async ({ toolkitSlug, query }: { toolkitSlug: string; query?: string }) => {
|
||||||
|
console.log("🎯 AI TOOL CALL: search_relevant_triggers", { toolkitSlug, query });
|
||||||
|
const result = await searchRelevantTriggers(usageTracker, toolkitSlug, query);
|
||||||
|
console.log("✅ AI TOOL CALL COMPLETED: search_relevant_triggers", {
|
||||||
|
toolkitSlug,
|
||||||
|
query,
|
||||||
|
resultLength: result.length,
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
messages: [
|
messages: [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -199,7 +199,48 @@ Note: The agents have access to a tool called 'Generate Image'. This won't show
|
||||||
|
|
||||||
## Section: Creating Triggers
|
## Section: Creating Triggers
|
||||||
|
|
||||||
Triggers are automated mechanisms that activate your agents at specific times or intervals. You can create two types of triggers:
|
Triggers are automated mechanisms that activate your agents at specific times or intervals. Evaluate every user request for automation or event driven tasks. If the user needs something to happen when an external event occurs (for example a new email, calendar invite, CRM update, or chat message), plan to add an external trigger after confirming the correct integration.
|
||||||
|
|
||||||
|
### Trigger Tool Search
|
||||||
|
- Use the "search_relevant_triggers" tool whenever you need to discover external triggers. Provide a toolkit slug (for example "gmail") and optionally keywords from the user's request.
|
||||||
|
- Do not invent trigger names. Always call the tool to confirm that the trigger exists before adding it to the workflow.
|
||||||
|
- After selecting a trigger, create an "external_trigger" action that references the trigger type slug and any required configuration fields.
|
||||||
|
|
||||||
|
### Trigger Toolkits Library
|
||||||
|
- Gmail (slug: gmail) - Gmail is Google's email service, featuring spam protection, search functions, and seamless integration with other G Suite apps for productivity.
|
||||||
|
- GitHub (slug: github) - GitHub is a code hosting platform for version control and collaboration, offering Git based repository management, issue tracking, and continuous integration features.
|
||||||
|
- Google Calendar (slug: googlecalendar) - Google Calendar is a time management tool providing scheduling features, event reminders, and integration with email and other apps for streamlined organization.
|
||||||
|
- Notion (slug: notion) - Notion centralizes notes, docs, wikis, and tasks in a unified workspace, letting teams build custom workflows for collaboration and knowledge management.
|
||||||
|
- Google Sheets (slug: googlesheets) - Google Sheets is a cloud based spreadsheet tool enabling real time collaboration, data analysis, and integration with other Google Workspace apps.
|
||||||
|
- Slack (slug: slack) - Slack is a channel based messaging platform that helps teams collaborate, integrate software tools, and surface information within a secure environment.
|
||||||
|
- Outlook (slug: outlook) - Outlook is Microsoft's email and calendaring platform integrating contacts, tasks, and scheduling so users can manage communications and events together.
|
||||||
|
- Google Drive (slug: googledrive) - Google Drive is a cloud storage solution for uploading, sharing, and collaborating on files across devices, with robust search and offline access.
|
||||||
|
- Google Docs (slug: googledocs) - Google Docs is a cloud based word processor with real time collaboration, version history, and integration with other Google Workspace apps.
|
||||||
|
- Hubspot (slug: hubspot) - HubSpot is an inbound marketing, sales, and customer service platform integrating CRM, email automation, and analytics to nurture leads and manage customer experiences.
|
||||||
|
- Linear (slug: linear) - Linear is a streamlined issue tracking and project planning tool for modern teams, featuring fast workflows, keyboard shortcuts, and GitHub integrations.
|
||||||
|
- Jira (slug: jira) - Jira is a tool for bug tracking, issue tracking, and agile project management.
|
||||||
|
- Youtube (slug: youtube) - YouTube is a video sharing platform supporting user generated content, live streaming, and monetization for marketing, education, and entertainment.
|
||||||
|
- Slackbot (slug: slackbot) - Slackbot automates responses and reminders within Slack, assisting with tasks like onboarding, FAQs, and notifications to streamline team productivity.
|
||||||
|
- Canvas (slug: canvas) - Canvas is a learning management system supporting online courses, assignments, grading, and collaboration for schools and universities.
|
||||||
|
- Discord (slug: discord) - Discord is an instant messaging and VoIP social platform.
|
||||||
|
- Asana (slug: asana) - Asana helps teams organize, track, and manage their work.
|
||||||
|
- One drive (slug: one_drive) - OneDrive is Microsoft's cloud storage solution enabling users to store, sync, and share files with offline access and enterprise security.
|
||||||
|
- Salesforce (slug: salesforce) - Salesforce is a CRM platform integrating sales, service, marketing, and analytics to build customer relationships and drive growth.
|
||||||
|
- Trello (slug: trello) - Trello is a web based, kanban style, list making application for organizing tasks.
|
||||||
|
- Stripe (slug: stripe) - Stripe offers online payment infrastructure, fraud prevention, and APIs enabling businesses to accept and manage payments globally.
|
||||||
|
- Mailchimp (slug: mailchimp) - Mailchimp is an email marketing and automation platform providing campaign templates, audience segmentation, and performance analytics.
|
||||||
|
- Fireflies (slug: fireflies) - Fireflies.ai helps teams transcribe, summarize, search, and analyze voice conversations.
|
||||||
|
- Coda (slug: coda) - Coda is a collaborative workspace platform that turns documents into powerful tools for team productivity and project management.
|
||||||
|
- Pipedrive (slug: pipedrive) - Pipedrive is a sales management tool centered on pipeline visualization, lead tracking, activity reminders, and automation.
|
||||||
|
- Zendesk (slug: zendesk) - Zendesk provides customer support software with ticketing, live chat, and knowledge base features for efficient helpdesk operations.
|
||||||
|
- Google Super (slug: googlesuper) - Google Super App combines Google services including Drive, Calendar, Gmail, Sheets, Analytics, and Ads for unified management.
|
||||||
|
- Todoist (slug: todoist) - Todoist is a task management tool for creating to do lists, setting deadlines, and collaborating with reminders and cross platform syncing.
|
||||||
|
- Agent mail (slug: agent_mail) - AgentMail gives AI agents their own email inboxes so they can send, receive, and act upon emails for communication with services, people, and other agents.
|
||||||
|
- Google Slides (slug: googleslides) - Google Slides is a cloud based presentation editor with real time collaboration, templates, and Workspace integrations.
|
||||||
|
- Spotify (slug: spotify) - Spotify is a digital music and podcast streaming service with personalized playlists and social sharing features.
|
||||||
|
- Timelinesai (slug: timelinesai) - TimelinesAI enables teams to manage and automate WhatsApp communications, integrating with CRMs to streamline workflows.
|
||||||
|
|
||||||
|
You can create two types of local triggers:
|
||||||
|
|
||||||
### One-Time Triggers
|
### One-Time Triggers
|
||||||
- Execute once at a specific date and time
|
- Execute once at a specific date and time
|
||||||
|
|
@ -361,4 +402,4 @@ Below are details you should use when a user asks questions on how to use the pr
|
||||||
{USING_ROWBOAT_DOCS}
|
{USING_ROWBOAT_DOCS}
|
||||||
|
|
||||||
</general_guidelines>
|
</general_guidelines>
|
||||||
`;
|
`;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue