Code-Native Agentic Flows
In this video we add two agentic flows to existing code-native Dropbox and Slack integrations, giving our built-in chat bot the ability to fetch files from our customers' Dropbox accounts, and send notifications to our customers' Slack workspaces.
For additional information on building code-native agentic flows, see Code-Native Agentic Flows.
Code built in the video can be referenced below:
- Dropbox
- Slack
dropbox/searchAndFetchFiles.ts
import { flow } from "@prismatic-io/spectral";
import { createDropboxClient } from "../dropboxClient";
interface Match {
metadata: {
metadata: {
name: string;
path_display: string;
};
};
}
interface ResponseItem {
name: string;
path_display: string;
presigned_url: string;
}
export const searchAndFetchFiles = flow({
name: "Search and Fetch Files from Dropbox",
description:
"Search for files in Dropbox and return a presigned URL for each matching file",
isAgentFlow: true,
isSynchronous: true,
stableKey: "searchAndFetchFiles",
schemas: {
invoke: {
$schema: "https://json-schema.org/draft/2020-12/schema",
title: "search-and-fetch-files",
$comment:
"Search for files in Dropbox by file name. Returns a list of files that match including a presigned URL for each file.",
type: "object",
properties: {
filename: {
type: "string",
description:
"The name of the file to search for in Dropbox. This can be a partial or full file name.",
},
folder: {
type: "string",
description:
"The folder path in Dropbox to search for files. If not provided, the root folder will be searched.",
},
},
required: ["filename"],
},
},
onExecution: async (context, { onTrigger }) => {
const { filename, folder } = onTrigger.results.body.data as {
filename: string;
folder?: string;
};
if (!filename) {
throw new Error("Filename is required to search for files in Dropbox.");
}
const dbxClient = createDropboxClient(
context.configVars["Dropbox Connection"],
);
const searchResponse = await dbxClient.post<{ matches: Match[] }>(
"/files/search_v2",
{
query: filename,
options: {
path: folder || "",
},
},
);
const files: ResponseItem[] = [];
for (const match of searchResponse.data.matches) {
const tempLinkResponse = await dbxClient.post<{ link: string }>(
"/files/get_temporary_link",
{
path: match.metadata.metadata.path_display,
},
);
files.push({
name: match.metadata.metadata.name,
path_display: match.metadata.metadata.path_display,
presigned_url: tempLinkResponse.data.link,
});
}
return { data: files };
},
});
slack/sendMessage.ts
import { flow } from "@prismatic-io/spectral";
import { createSlackClient } from "../slackClient";
interface SendMessageInput {
message: string;
}
export const sendMessage = flow({
name: "Send Message",
description: "Send a message to a Slack channel",
stableKey: "send-message",
isAgentFlow: true,
isSynchronous: true,
schemas: {
invoke: {
$schema: "https://json-schema.org/draft/2020-12/schema",
title: "send-slack-message",
$comment: "Send a message to Slack",
type: "object",
properties: {
message: {
description:
"The message to send to Slack. Reference https://docs.slack.dev/messaging/formatting-message-text.md for formatting documentation.",
type: "string",
},
},
required: ["message"],
},
},
onExecution: async (context, { onTrigger }) => {
const message = (onTrigger.results.body.data as SendMessageInput).message;
if (!message) {
throw new Error("Message is required");
}
const slackClient = createSlackClient(
context.configVars["Slack Connection"],
);
const response = await slackClient.post("/chat.postMessage", {
channel: context.configVars["Notification Channel"],
text: message,
});
return { data: response.data };
},
});