wise-white
wise-white2mo ago

Sample Code in "Build Tools Without Auth" asks for a connected account

Hi everyone, I just discovered Composio the other day and decided to give it a try. I am trying to use a custom script as a Custom Tool, and it led me to "Build Tools WIthout Auth" section in the docs: https://docs.composio.dev/patterns/tools/build-tools/custom-action-without-auth I copied everything in the page, combined them into a single script, and upon running, I was met with an error:
throw new Error("No connected account found for the user");
^

Error: No connected account found for the user
at OpenAIToolSet.executeAction
throw new Error("No connected account found for the user");
^

Error: No connected account found for the user
at OpenAIToolSet.executeAction
My script:
import { OpenAIToolSet } from "composio-core";
import dotenv from "dotenv";
import { OpenAI } from "openai";
import { z } from "zod"

const openai_client = new OpenAI();
const toolset = new OpenAIToolSet();

dotenv.config();

await toolset.createAction({
actionName: "myCustomAction",
description: "Cow will say whatever you want it to say",
inputParams: z.object({
message: z.string()
}),
callback: async (inputParams) => {
const message = inputParams.message;
const cowMessage = `Cow says: ${message}`;
// this is where I want to put the custom tool logic
return cowMessage;
}
});

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

const instruction = "Say 'AI is the future' using cowsay";

const response = await openai_client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: instruction }],
tools: tools,
tool_choice: "auto",
});

const result = await toolset.handleToolCall(response);
console.log(result);
import { OpenAIToolSet } from "composio-core";
import dotenv from "dotenv";
import { OpenAI } from "openai";
import { z } from "zod"

const openai_client = new OpenAI();
const toolset = new OpenAIToolSet();

dotenv.config();

await toolset.createAction({
actionName: "myCustomAction",
description: "Cow will say whatever you want it to say",
inputParams: z.object({
message: z.string()
}),
callback: async (inputParams) => {
const message = inputParams.message;
const cowMessage = `Cow says: ${message}`;
// this is where I want to put the custom tool logic
return cowMessage;
}
});

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

const instruction = "Say 'AI is the future' using cowsay";

const response = await openai_client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: instruction }],
tools: tools,
tool_choice: "auto",
});

const result = await toolset.handleToolCall(response);
console.log(result);
I really wonder what I am missing here.
Composio Docs
Build Tools Without Auth - Composio
Composio enables your agents to connect with Various Tools and work with them
6 Replies
ambitious-aqua
ambitious-aqua2mo ago
Strange, can we have a small meet so I can see the issue better @Raymel (@pseudokid on X) ?? You can tell me your available time in IST
wise-white
wise-whiteOP2mo ago
I realized that I skipped the authentication process. I believe this will get resolved once I get past the authentication. I'm having issues with the CLI though, I detailed it on the other thread.
wise-white
wise-whiteOP2mo ago
I already ran composio login and I successfully authenticated myself However, running the script I made (which I derived exactly from the doc example) still leads to the same error
/node_modules/composio-core/index.js:3975
throw new Error("No connected account found for the user")
/node_modules/composio-core/index.js:3975
throw new Error("No connected account found for the user")
I made a quick scan to the code that throws the said exception, and now I need to figure out where I can find this accountId because the code requires it. This is the exact code that requires it: node_modules/composio-core/index.js:3975:23:
// Custom actions are always executed in the host/local environment for JS SDK
if (await this.isCustomAction(action)) {
let accountId = connectedAccountId;
if (!accountId) {
// fetch connected account id
const connectedAccounts = await this.client.connectedAccounts.list({
user_uuid: entityId,
status: "ACTIVE",
showActiveOnly: true,
});
accountId = (_a = connectedAccounts === null || connectedAccounts === void 0 ? void 0 : connectedAccounts.items[0]) === null || _a === void 0 ? void 0 : _a.id;
}
if (!accountId) {
throw new Error("No connected account found for the user");
}
return this.userActionRegistry.executeAction(action, params, {
entityId: entityId,
connectionId: accountId,
});
}
// Custom actions are always executed in the host/local environment for JS SDK
if (await this.isCustomAction(action)) {
let accountId = connectedAccountId;
if (!accountId) {
// fetch connected account id
const connectedAccounts = await this.client.connectedAccounts.list({
user_uuid: entityId,
status: "ACTIVE",
showActiveOnly: true,
});
accountId = (_a = connectedAccounts === null || connectedAccounts === void 0 ? void 0 : connectedAccounts.items[0]) === null || _a === void 0 ? void 0 : _a.id;
}
if (!accountId) {
throw new Error("No connected account found for the user");
}
return this.userActionRegistry.executeAction(action, params, {
entityId: entityId,
connectionId: accountId,
});
}
The thing is, this requirement is not explicitly detailed on the "Build Tools Without Auth" section in the docs: https://docs.composio.dev/patterns/tools/build-tools/custom-action-without-auth Now, I wonder if a connected account is necessary for a custom action. If it is by design, I don't think I will be able to use composio for my very simple use case that does not even need a connected account.
Composio Docs
Build Tools Without Auth - Composio
Composio enables your agents to connect with Various Tools and work with them
wise-white
wise-whiteOP2mo ago
I was able to run my code by commenting-out the root cause in node_modules/composio-core/index.js:3975:23:
// Custom actions are always executed in the host/local environment for JS SDK
if (await this.isCustomAction(action)) {
let accountId = connectedAccountId;
// if (!accountId) {
// // fetch connected account id
// const connectedAccounts = await this.client.connectedAccounts.list({
// user_uuid: entityId,
// status: "ACTIVE",
// showActiveOnly: true,
// });
// accountId = (_a = connectedAccounts === null || connectedAccounts === void 0 ? void 0 : connectedAccounts.items[0]) === null || _a === void 0 ? void 0 : _a.id;
// }
// if (!accountId) {
// throw new Error("No connected account found for the user");
// }
return this.userActionRegistry.executeAction(action, params, {
entityId: entityId,
connectionId: accountId,
});
}
// Custom actions are always executed in the host/local environment for JS SDK
if (await this.isCustomAction(action)) {
let accountId = connectedAccountId;
// if (!accountId) {
// // fetch connected account id
// const connectedAccounts = await this.client.connectedAccounts.list({
// user_uuid: entityId,
// status: "ACTIVE",
// showActiveOnly: true,
// });
// accountId = (_a = connectedAccounts === null || connectedAccounts === void 0 ? void 0 : connectedAccounts.items[0]) === null || _a === void 0 ? void 0 : _a.id;
// }
// if (!accountId) {
// throw new Error("No connected account found for the user");
// }
return this.userActionRegistry.executeAction(action, params, {
entityId: entityId,
connectionId: accountId,
});
}
This proves my assumption right, that custom actions are requiring connections. I also believe that it is unnecessary to require a connection for a custom action, given that I was able to run my code without one. If I am on the right track, please let me know where I can modify the SDK code and make a Pull Request.
extended-salmon
extended-salmon2mo ago
sorry for the delay here. this is weird - custom actions should also work without connection (auth). shared this with the team - let me get back to you on this quickly.
ambitious-aqua
ambitious-aqua3w ago
Hey @Raymel (@pseudokid on X), could you check if it is working for you or not right now??

Did you find this page helpful?