subsequent-cyan
subsequent-cyanโ€ข6mo ago

[Solved โœ…] Running Composio locally? Error when trying to start

I get this error:
$ node index.mjs
[DEBUG] 12:57:52 Creating workspace with env=HOST and kwargs={"composioBaseURL":"https://backend.composio.dev/","composioAPIKey":"xx"}
[WARN] 12:57:52 Local tools are not supported in host environment - see docs https://docs.composio.dev/swekit-js/workspace-env
$ node index.mjs
[DEBUG] 12:57:52 Creating workspace with env=HOST and kwargs={"composioBaseURL":"https://backend.composio.dev/","composioAPIKey":"xx"}
[WARN] 12:57:52 Local tools are not supported in host environment - see docs https://docs.composio.dev/swekit-js/workspace-env
No description
15 Replies
subsequent-cyan
subsequent-cyanOPโ€ข6mo ago
Trying out Composio, but when i try to run this simple test i get error. Any clue? Im trying to fetch my emails through composio
continuing-cyan
continuing-cyanโ€ข6mo ago
Hey @Em , this is just a warning which should not cause any issue in your case. Is this the complete code?
subsequent-cyan
subsequent-cyanOPโ€ข6mo ago
yeah oh im dumb man
subsequent-cyan
subsequent-cyanOPโ€ข6mo ago
No description
subsequent-cyan
subsequent-cyanOPโ€ข6mo ago
tryign to do this and i feel like im missing something my output looks like this right now
[WARN] 13:17:40 Local tools are not supported in host environment - see docs https://docs.composio.dev/swekit-js/workspace-env
[
DynamicStructuredTool {
lc_serializable: false,
lc_kwargs: {
name: 'GMAIL_FETCH_EMAILS',
description: 'Action to fetch all emails from Gmail.',
schema: [ZodObject],
func: [AsyncFunction: func]
},
lc_runnable: true,
name: 'GMAIL_FETCH_EMAILS',
verbose: false,
callbacks: undefined,
tags: [],
metadata: {},
returnDirect: false,
verboseParsingErrors: false,
responseFormat: 'content',
description: 'Action to fetch all emails from Gmail.',
func: [AsyncFunction: func],
schema: ZodObject {
spa: [Function: bound safeParseAsync] AsyncFunction,
_def: [Object],
parse: [Function: bound parse],
safeParse: [Function: bound safeParse],
parseAsync: [Function: bound parseAsync] AsyncFunction,
safeParseAsync: [Function: bound safeParseAsync] AsyncFunction,
refine: [Function: bound refine],
refinement: [Function: bound refinement],
superRefine: [Function: bound superRefine],
optional: [Function: bound optional],
nullable: [Function: bound nullable],
nullish: [Function: bound nullish],
array: [Function: bound array],
promise: [Function: bound promise],
or: [Function: bound or],
and: [Function: bound and],
transform: [Function: bound transform],
brand: [Function: bound brand],
default: [Function: bound default],
catch: [Function: bound catch],
describe: [Function: bound describe],
pipe: [Function: bound pipe],
readonly: [Function: bound readonly],
isNullable: [Function: bound isNullable],
isOptional: [Function: bound isOptional],
_cached: null,
nonstrict: [Function: passthrough],
augment: [Function: extend]
}
}
]
[WARN] 13:17:40 Local tools are not supported in host environment - see docs https://docs.composio.dev/swekit-js/workspace-env
[
DynamicStructuredTool {
lc_serializable: false,
lc_kwargs: {
name: 'GMAIL_FETCH_EMAILS',
description: 'Action to fetch all emails from Gmail.',
schema: [ZodObject],
func: [AsyncFunction: func]
},
lc_runnable: true,
name: 'GMAIL_FETCH_EMAILS',
verbose: false,
callbacks: undefined,
tags: [],
metadata: {},
returnDirect: false,
verboseParsingErrors: false,
responseFormat: 'content',
description: 'Action to fetch all emails from Gmail.',
func: [AsyncFunction: func],
schema: ZodObject {
spa: [Function: bound safeParseAsync] AsyncFunction,
_def: [Object],
parse: [Function: bound parse],
safeParse: [Function: bound safeParse],
parseAsync: [Function: bound parseAsync] AsyncFunction,
safeParseAsync: [Function: bound safeParseAsync] AsyncFunction,
refine: [Function: bound refine],
refinement: [Function: bound refinement],
superRefine: [Function: bound superRefine],
optional: [Function: bound optional],
nullable: [Function: bound nullable],
nullish: [Function: bound nullish],
array: [Function: bound array],
promise: [Function: bound promise],
or: [Function: bound or],
and: [Function: bound and],
transform: [Function: bound transform],
brand: [Function: bound brand],
default: [Function: bound default],
catch: [Function: bound catch],
describe: [Function: bound describe],
pipe: [Function: bound pipe],
readonly: [Function: bound readonly],
isNullable: [Function: bound isNullable],
isOptional: [Function: bound isOptional],
_cached: null,
nonstrict: [Function: passthrough],
augment: [Function: extend]
}
}
]
continuing-cyan
continuing-cyanโ€ข6mo ago
Oh okay - this makes sense, there are two things to note here 1. Basically the code snippet above only allows you to get composio tools for "Gmail fetch emails" actions - just like in the output you sent above. You need to plug it into your agentic framework - which will allow your agent to decide and call this action to fetch emails.
continuing-cyan
continuing-cyanโ€ข6mo ago
GitHub
composio/js/examples/langchain/demo.mjs at master ยท ComposioHQ/comp...
Composio equip's your AI agents & LLMs with 100+ high-quality integrations via function calling - ComposioHQ/composio
continuing-cyan
continuing-cyanโ€ข6mo ago
2. Also remove the second argument from toolset.getTools . It is there to filter your users with tags but in your case since you are just trying it out - for now you can remove it. After this your line 18 should look like this
const tools = await toolset.getTools({ actions: ["GMAIL_FETCH_EMAILS"] });
const tools = await toolset.getTools({ actions: ["GMAIL_FETCH_EMAILS"] });
subsequent-cyan
subsequent-cyanOPโ€ข6mo ago
ok @Utkarsh i did some updates it seems to work
import express from 'express';
import dotenv from 'dotenv';
import { ChatOpenAI } from "@langchain/openai";
import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents";
import { pull } from "langchain/hub";

import pkg from 'composio-core';
const { LangchainToolSet, ExecEnv } = pkg;

const app = express();
const PORT = process.env.PORT || 2001;
dotenv.config();
app.use(express.json());

(async () => {
try {

const llm = new ChatOpenAI({
model: "gpt-4-turbo",
openAIApiKey: process.env.OPENAI_API_KEY,
});

const toolset = new LangchainToolSet({
apiKey: process.env.COMPOSIO_API_KEY
});


const tools = await toolset.getTools({ actions: ["GMAIL_FETCH_EMAILS"] });

const prompt = await pull(
"hwchase17/openai-functions-agent"
);

const agent = await createOpenAIFunctionsAgent({
llm,
tools,
prompt,
});

const agentExecutor = new AgentExecutor({
agent,
tools,
verbose: true,
});

const result = await agentExecutor.invoke({
input: "Tell me if there are any important emails"
});

} catch (error) {
console.error(error);
}
})();
import express from 'express';
import dotenv from 'dotenv';
import { ChatOpenAI } from "@langchain/openai";
import { createOpenAIFunctionsAgent, AgentExecutor } from "langchain/agents";
import { pull } from "langchain/hub";

import pkg from 'composio-core';
const { LangchainToolSet, ExecEnv } = pkg;

const app = express();
const PORT = process.env.PORT || 2001;
dotenv.config();
app.use(express.json());

(async () => {
try {

const llm = new ChatOpenAI({
model: "gpt-4-turbo",
openAIApiKey: process.env.OPENAI_API_KEY,
});

const toolset = new LangchainToolSet({
apiKey: process.env.COMPOSIO_API_KEY
});


const tools = await toolset.getTools({ actions: ["GMAIL_FETCH_EMAILS"] });

const prompt = await pull(
"hwchase17/openai-functions-agent"
);

const agent = await createOpenAIFunctionsAgent({
llm,
tools,
prompt,
});

const agentExecutor = new AgentExecutor({
agent,
tools,
verbose: true,
});

const result = await agentExecutor.invoke({
input: "Tell me if there are any important emails"
});

} catch (error) {
console.error(error);
}
})();
@Utkarsh do you know how i change it so that my emails are limited to the past 24 hours? ๐Ÿค”
continuing-cyan
continuing-cyanโ€ข6mo ago
yes, although I haven't tried it myself - gmail search queries support good advanced filters. you can try mentioning it explicitly in your agentExecutorInput to use it. Something like this should work
const result = await agentExecutor.invoke({
input: "Tell me if there are any important emails in last 1d. Please use this search filter in the query to filter the emails for last 1d, newer_than:1d "
});
const result = await agentExecutor.invoke({
input: "Tell me if there are any important emails in last 1d. Please use this search filter in the query to filter the emails for last 1d, newer_than:1d "
});
Check this doc for more detail on gmail query filters - https://support.google.com/mail/answer/7190?hl=en
Refine searches in Gmail - Computer - Gmail Help
Want to get more out of Google apps at work or school?
subsequent-cyan
subsequent-cyanOPโ€ข6mo ago
Oh. Composio is a lot more powerful than i though then haha @Utkarsh thanks a lot ๐Ÿ’Ÿ is it possible to do two actions in one command? forexample if i add a label to the email it reads?
(async () => {
try {

const tools = await toolset.getTools({ actions: ["GMAIL_FETCH_EMAILS", "GMAIL_ADD_LABEL_TO_EMAIL"]});

const agent = await createOpenAIFunctionsAgent({
llm,
tools,
prompt,
});

const agentExecutor = new AgentExecutor({
agent,
tools,
verbose: false,
});

const result = await agentExecutor.invoke({
input: "Write a short list of each important email, limit to 15 words per email. Keep in mind I am Emil, and i dont consider my own emails important, ONLY INCLUDE EMAILS from important clients, partners or bills. Email from services (ie hubspot, stripe, amazon etc). IF the email title is not in English or Swedish, Please translate it to english and add the translated text after in paranthesis. or appstores should be ignored. DO NOT GIVE ANYTHING OTHER THAN THE EMAIL INFO. Use markdown formatting and Bold the titles!, Add space between each item. Bold the title. Add date of email to the output. Please use this search filter in the query to filter the emails for last 1d, newer_than:1d. After you read them please add a label called AIREAD to them "
});

console.log("result:",result.output);
try {
console.log("We got real format")
await bot.sendMessage(process.env.TELEGRAM_CHAT_ID, result.output, { parse_mode: 'Markdown' });
} catch (error) {
console.log("We got no format")

await bot.sendMessage(process.env.TELEGRAM_CHAT_ID, result.output);
}

} catch (error) {
console.error(error);
}
})();
(async () => {
try {

const tools = await toolset.getTools({ actions: ["GMAIL_FETCH_EMAILS", "GMAIL_ADD_LABEL_TO_EMAIL"]});

const agent = await createOpenAIFunctionsAgent({
llm,
tools,
prompt,
});

const agentExecutor = new AgentExecutor({
agent,
tools,
verbose: false,
});

const result = await agentExecutor.invoke({
input: "Write a short list of each important email, limit to 15 words per email. Keep in mind I am Emil, and i dont consider my own emails important, ONLY INCLUDE EMAILS from important clients, partners or bills. Email from services (ie hubspot, stripe, amazon etc). IF the email title is not in English or Swedish, Please translate it to english and add the translated text after in paranthesis. or appstores should be ignored. DO NOT GIVE ANYTHING OTHER THAN THE EMAIL INFO. Use markdown formatting and Bold the titles!, Add space between each item. Bold the title. Add date of email to the output. Please use this search filter in the query to filter the emails for last 1d, newer_than:1d. After you read them please add a label called AIREAD to them "
});

console.log("result:",result.output);
try {
console.log("We got real format")
await bot.sendMessage(process.env.TELEGRAM_CHAT_ID, result.output, { parse_mode: 'Markdown' });
} catch (error) {
console.log("We got no format")

await bot.sendMessage(process.env.TELEGRAM_CHAT_ID, result.output);
}

} catch (error) {
console.error(error);
}
})();
this is an updated version
continuing-cyan
continuing-cyanโ€ข6mo ago
Yes, this is totally possible with same code you sent above but would require you to modify your prompt to be very specific. To increase the accuracy, I'd actually recommend creating separate sepcific agents instead of single agent for this 1. The first agents only fetches the latest emails and removes all the unecessary info. Make sure to mention to also include the messageId in the final output (this will be needed by second agent when it is adding labels) 2. The second agent adds labels to these emails You can simply pass the output of the first agent to the second output as the task. Something like Add label to all these emails: ${firstAgentOutput}
optimistic-gold
optimistic-goldโ€ข5mo ago
Hey @Em, is your issue resolved ๐Ÿ˜„ ??
subsequent-cyan
subsequent-cyanOPโ€ข5mo ago
Yes ๐Ÿ™ƒ
optimistic-gold
optimistic-goldโ€ข5mo ago
Awesome @Em, lemme know if you need any other help, till then keep exploring composio ๐Ÿ˜‰

Did you find this page helpful?