@customclaw/composio 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,184 @@
1
+ # Composio Tool Router Plugin for OpenClaw
2
+
3
+ Access 1000+ third-party tools through Composio's unified Tool Router interface.
4
+
5
+ ## Features
6
+
7
+ - **Search Tools**: Find tools by describing what you want to accomplish
8
+ - **Execute Tools**: Run any tool with authenticated connections
9
+ - **Multi-Execute**: Run up to 50 tools in parallel
10
+ - **Connection Management**: Connect to toolkits via OAuth or API keys
11
+
12
+ ## Supported Integrations
13
+
14
+ Gmail, Slack, GitHub, Notion, Linear, Jira, HubSpot, Salesforce, Google Drive, Asana, Trello, and 1000+ more.
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ openclaw plugins install @customclaw/composio
20
+ ```
21
+
22
+ ## Configuration
23
+
24
+ ### Option 1: Environment Variable
25
+
26
+ ```bash
27
+ export COMPOSIO_API_KEY=your-api-key
28
+ ```
29
+
30
+ ### Option 2: OpenClaw Config
31
+
32
+ Add to `~/.openclaw/openclaw.json`:
33
+
34
+ ```json
35
+ {
36
+ "plugins": {
37
+ "entries": {
38
+ "composio": {
39
+ "enabled": true,
40
+ "config": {
41
+ "apiKey": "your-api-key",
42
+ "defaultUserId": "client-companyname-uuid",
43
+ "allowedToolkits": ["gmail", "sentry"]
44
+ }
45
+ }
46
+ }
47
+ }
48
+ }
49
+ ```
50
+
51
+ Get your API key from [platform.composio.dev/settings](https://platform.composio.dev/settings).
52
+
53
+ ## CLI Commands
54
+
55
+ ```bash
56
+ # List available toolkits
57
+ openclaw composio list
58
+
59
+ # Check connection status
60
+ openclaw composio status
61
+ openclaw composio status github
62
+
63
+ # Connect to a toolkit (opens auth URL)
64
+ openclaw composio connect github
65
+ openclaw composio connect gmail
66
+
67
+ # Disconnect from a toolkit
68
+ openclaw composio disconnect github
69
+
70
+ # Search for tools
71
+ openclaw composio search "send email"
72
+ openclaw composio search "create issue" --toolkit github
73
+ ```
74
+
75
+ ## Agent Tools
76
+
77
+ The plugin provides six tools for agents:
78
+
79
+ ### `composio_search_tools`
80
+
81
+ Search for tools matching a task description.
82
+
83
+ ```json
84
+ {
85
+ "query": "send an email with attachment",
86
+ "toolkits": ["gmail"],
87
+ "limit": 5
88
+ }
89
+ ```
90
+
91
+ ### `composio_execute_tool`
92
+
93
+ Execute a single tool.
94
+
95
+ ```json
96
+ {
97
+ "tool_slug": "GMAIL_SEND_EMAIL",
98
+ "arguments": {
99
+ "to": "user@example.com",
100
+ "subject": "Hello",
101
+ "body": "Message content"
102
+ }
103
+ }
104
+ ```
105
+
106
+ ### `composio_multi_execute`
107
+
108
+ Execute multiple tools in parallel (up to 50).
109
+
110
+ ```json
111
+ {
112
+ "executions": [
113
+ { "tool_slug": "GITHUB_CREATE_ISSUE", "arguments": { "title": "Bug", "repo": "org/repo" } },
114
+ { "tool_slug": "SLACK_SEND_MESSAGE", "arguments": { "channel": "#dev", "text": "Issue created" } }
115
+ ]
116
+ }
117
+ ```
118
+
119
+ ### `composio_manage_connections`
120
+
121
+ Manage toolkit connections.
122
+
123
+ ```json
124
+ {
125
+ "action": "status",
126
+ "toolkits": ["github", "gmail"]
127
+ }
128
+ ```
129
+
130
+ ### `composio_workbench`
131
+
132
+ Execute Python code in a remote Jupyter sandbox.
133
+
134
+ ### `composio_bash`
135
+
136
+ Execute bash commands in a remote sandbox.
137
+
138
+ ## Advanced Configuration
139
+
140
+ ```json
141
+ {
142
+ "plugins": {
143
+ "entries": {
144
+ "composio": {
145
+ "enabled": true,
146
+ "config": {
147
+ "apiKey": "your-api-key",
148
+ "defaultUserId": "user_123",
149
+ "allowedToolkits": ["github", "gmail", "slack"],
150
+ "blockedToolkits": ["dangerous-toolkit"]
151
+ }
152
+ }
153
+ }
154
+ }
155
+ }
156
+ ```
157
+
158
+ ## Updating
159
+
160
+ ```bash
161
+ openclaw plugins update @customclaw/composio
162
+ openclaw gateway restart
163
+ ```
164
+
165
+ Gateway restart is required after updates.
166
+
167
+ ## Development
168
+
169
+ ```bash
170
+ npm install
171
+ npm run build
172
+ npm pack # creates .tgz for local testing
173
+ openclaw plugins install ./customclaw-composio-0.0.1.tgz
174
+ ```
175
+
176
+ ## Acknowledgments
177
+
178
+ This project is based on the Composio plugin from [openclaw-composio](https://github.com/ComposioHQ/openclaw-composio) by ComposioHQ. See [THIRD-PARTY-NOTICES](./THIRD-PARTY-NOTICES) for details.
179
+
180
+ ## Links
181
+
182
+ - [Composio Documentation](https://docs.composio.dev)
183
+ - [Tool Router Overview](https://docs.composio.dev/tool-router/overview)
184
+ - [Composio Platform](https://platform.composio.dev)
@@ -0,0 +1,31 @@
1
+ This project is based on the Composio plugin from:
2
+ https://github.com/ComposioHQ/openclaw-composio
3
+
4
+ That repository is a fork of OpenClaw with the Composio plugin added by the
5
+ ComposioHQ team. The repository-level MIT license (Copyright (c) 2025 Peter
6
+ Steinberger) covers the OpenClaw codebase, not the Composio plugin specifically.
7
+
8
+ The Composio plugin code (under extensions/composio/) was authored by ComposioHQ.
9
+ We include the repo's MIT license below as it covers the repository as a whole:
10
+
11
+ MIT License
12
+
13
+ Copyright (c) 2025 Peter Steinberger
14
+
15
+ Permission is hereby granted, free of charge, to any person obtaining a copy
16
+ of this software and associated documentation files (the "Software"), to deal
17
+ in the Software without restriction, including without limitation the rights
18
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19
+ copies of the Software, and to permit persons to whom the Software is
20
+ furnished to do so, subject to the following conditions:
21
+
22
+ The above copyright notice and this permission notice shall be included in all
23
+ copies or substantial portions of the Software.
24
+
25
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
+ SOFTWARE.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ import type { ComposioClient } from "./client.js";
2
+ import type { ComposioConfig } from "./types.js";
3
+ interface PluginLogger {
4
+ info(msg: string): void;
5
+ warn(msg: string): void;
6
+ error(msg: string): void;
7
+ }
8
+ interface RegisterCliOptions {
9
+ program: any;
10
+ client: ComposioClient;
11
+ config: ComposioConfig;
12
+ logger: PluginLogger;
13
+ }
14
+ /**
15
+ * Register Composio CLI commands
16
+ */
17
+ export declare function registerComposioCli({ program, client, config, logger }: RegisterCliOptions): void;
18
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Register Composio CLI commands
3
+ */
4
+ export function registerComposioCli({ program, client, config, logger }) {
5
+ const composio = program.command("composio").description("Manage Composio Tool Router connections");
6
+ // openclaw composio list
7
+ composio
8
+ .command("list")
9
+ .description("List available Composio toolkits")
10
+ .action(async () => {
11
+ if (!config.enabled) {
12
+ logger.error("Composio plugin is disabled");
13
+ return;
14
+ }
15
+ try {
16
+ const toolkits = await client.listToolkits();
17
+ console.log("\nAvailable Composio Toolkits:");
18
+ console.log("─".repeat(40));
19
+ for (const toolkit of toolkits.sort()) {
20
+ console.log(` ${toolkit}`);
21
+ }
22
+ console.log(`\nTotal: ${toolkits.length} toolkits`);
23
+ }
24
+ catch (err) {
25
+ logger.error(`Failed to list toolkits: ${err instanceof Error ? err.message : String(err)}`);
26
+ }
27
+ });
28
+ // openclaw composio status [toolkit]
29
+ composio
30
+ .command("status [toolkit]")
31
+ .description("Check connection status for toolkits")
32
+ .option("-u, --user-id <userId>", "User ID for session scoping")
33
+ .action(async (toolkit, options) => {
34
+ if (!config.enabled) {
35
+ logger.error("Composio plugin is disabled");
36
+ return;
37
+ }
38
+ try {
39
+ const toolkits = toolkit ? [toolkit] : undefined;
40
+ const statuses = await client.getConnectionStatus(toolkits, options.userId);
41
+ console.log("\nComposio Connection Status:");
42
+ console.log("─".repeat(40));
43
+ if (statuses.length === 0) {
44
+ console.log(" No connections found");
45
+ }
46
+ else {
47
+ for (const status of statuses) {
48
+ const icon = status.connected ? "✓" : "✗";
49
+ const state = status.connected ? "connected" : "not connected";
50
+ console.log(` ${icon} ${status.toolkit}: ${state}`);
51
+ }
52
+ }
53
+ console.log();
54
+ }
55
+ catch (err) {
56
+ logger.error(`Failed to get status: ${err instanceof Error ? err.message : String(err)}`);
57
+ }
58
+ });
59
+ // openclaw composio connect <toolkit>
60
+ composio
61
+ .command("connect <toolkit>")
62
+ .description("Connect to a Composio toolkit (opens auth URL)")
63
+ .option("-u, --user-id <userId>", "User ID for session scoping")
64
+ .action(async (toolkit, options) => {
65
+ if (!config.enabled) {
66
+ logger.error("Composio plugin is disabled");
67
+ return;
68
+ }
69
+ try {
70
+ console.log(`\nInitiating connection to ${toolkit}...`);
71
+ const result = await client.createConnection(toolkit, options.userId);
72
+ if ("error" in result) {
73
+ logger.error(`Failed to create connection: ${result.error}`);
74
+ return;
75
+ }
76
+ console.log("\nAuth URL generated:");
77
+ console.log("─".repeat(40));
78
+ console.log(result.authUrl);
79
+ console.log("\nOpen this URL in your browser to authenticate.");
80
+ console.log("After authentication, run 'openclaw composio status' to verify.\n");
81
+ // Try to open URL in browser
82
+ try {
83
+ const { exec } = await import("node:child_process");
84
+ const platform = process.platform;
85
+ const cmd = platform === "darwin"
86
+ ? `open "${result.authUrl}"`
87
+ : platform === "win32"
88
+ ? `start "" "${result.authUrl}"`
89
+ : `xdg-open "${result.authUrl}"`;
90
+ exec(cmd);
91
+ }
92
+ catch {
93
+ // Silently fail if we can't open browser
94
+ }
95
+ }
96
+ catch (err) {
97
+ logger.error(`Failed to connect: ${err instanceof Error ? err.message : String(err)}`);
98
+ }
99
+ });
100
+ // openclaw composio disconnect <toolkit>
101
+ composio
102
+ .command("disconnect <toolkit>")
103
+ .description("Disconnect from a Composio toolkit")
104
+ .option("-u, --user-id <userId>", "User ID for session scoping")
105
+ .action(async (toolkit, options) => {
106
+ if (!config.enabled) {
107
+ logger.error("Composio plugin is disabled");
108
+ return;
109
+ }
110
+ try {
111
+ console.log(`\nDisconnecting from ${toolkit}...`);
112
+ const result = await client.disconnectToolkit(toolkit, options.userId);
113
+ if (result.success) {
114
+ console.log(`Successfully disconnected from ${toolkit}\n`);
115
+ }
116
+ else {
117
+ logger.error(`Failed to disconnect: ${result.error}`);
118
+ }
119
+ }
120
+ catch (err) {
121
+ logger.error(`Failed to disconnect: ${err instanceof Error ? err.message : String(err)}`);
122
+ }
123
+ });
124
+ // openclaw composio search <query>
125
+ composio
126
+ .command("search <query>")
127
+ .description("Search for tools matching a query")
128
+ .option("-t, --toolkit <toolkit>", "Limit search to a specific toolkit")
129
+ .option("-l, --limit <limit>", "Maximum results", "10")
130
+ .option("-u, --user-id <userId>", "User ID for session scoping")
131
+ .action(async (query, options) => {
132
+ if (!config.enabled) {
133
+ logger.error("Composio plugin is disabled");
134
+ return;
135
+ }
136
+ try {
137
+ const limit = parseInt(options.limit, 10) || 10;
138
+ const toolkits = options.toolkit ? [options.toolkit] : undefined;
139
+ const results = await client.searchTools(query, {
140
+ toolkits,
141
+ limit,
142
+ userId: options.userId,
143
+ });
144
+ console.log(`\nSearch results for "${query}":`);
145
+ console.log("─".repeat(60));
146
+ if (results.length === 0) {
147
+ console.log(" No tools found matching your query");
148
+ }
149
+ else {
150
+ for (const tool of results) {
151
+ console.log(`\n ${tool.slug}`);
152
+ console.log(` Toolkit: ${tool.toolkit}`);
153
+ console.log(` ${tool.description.slice(0, 100)}${tool.description.length > 100 ? "..." : ""}`);
154
+ }
155
+ }
156
+ console.log(`\nTotal: ${results.length} tools found\n`);
157
+ }
158
+ catch (err) {
159
+ logger.error(`Failed to search: ${err instanceof Error ? err.message : String(err)}`);
160
+ }
161
+ });
162
+ }
@@ -0,0 +1,94 @@
1
+ import type { ComposioConfig, ToolSearchResult, ToolExecutionResult, MultiExecutionItem, MultiExecutionResult, ConnectionStatus } from "./types.js";
2
+ /**
3
+ * Composio client wrapper using Tool Router pattern
4
+ */
5
+ export declare class ComposioClient {
6
+ private client;
7
+ private config;
8
+ private sessionCache;
9
+ constructor(config: ComposioConfig);
10
+ /**
11
+ * Get the user ID to use for API calls
12
+ */
13
+ private getUserId;
14
+ /**
15
+ * Get or create a Tool Router session for a user
16
+ */
17
+ private getSession;
18
+ /**
19
+ * Check if a toolkit is allowed based on config
20
+ */
21
+ private isToolkitAllowed;
22
+ /**
23
+ * Execute a Tool Router meta-tool
24
+ */
25
+ private executeMetaTool;
26
+ /**
27
+ * Search for tools matching a query using COMPOSIO_SEARCH_TOOLS
28
+ */
29
+ searchTools(query: string, options?: {
30
+ toolkits?: string[];
31
+ limit?: number;
32
+ userId?: string;
33
+ }): Promise<ToolSearchResult[]>;
34
+ /**
35
+ * Execute a single tool using COMPOSIO_MULTI_EXECUTE_TOOL
36
+ */
37
+ executeTool(toolSlug: string, args: Record<string, unknown>, userId?: string): Promise<ToolExecutionResult>;
38
+ /**
39
+ * Execute multiple tools in parallel using COMPOSIO_MULTI_EXECUTE_TOOL
40
+ */
41
+ multiExecute(executions: MultiExecutionItem[], userId?: string): Promise<MultiExecutionResult>;
42
+ /**
43
+ * Get connection status for toolkits using session.toolkits()
44
+ */
45
+ getConnectionStatus(toolkits?: string[], userId?: string): Promise<ConnectionStatus[]>;
46
+ /**
47
+ * Create an auth connection for a toolkit using session.authorize()
48
+ */
49
+ createConnection(toolkit: string, userId?: string): Promise<{
50
+ authUrl: string;
51
+ } | {
52
+ error: string;
53
+ }>;
54
+ /**
55
+ * List available toolkits
56
+ */
57
+ listToolkits(userId?: string): Promise<string[]>;
58
+ /**
59
+ * Disconnect a toolkit
60
+ */
61
+ disconnectToolkit(toolkit: string, userId?: string): Promise<{
62
+ success: boolean;
63
+ error?: string;
64
+ }>;
65
+ /**
66
+ * Get the assistive prompt for the agent
67
+ */
68
+ getAssistivePrompt(userId?: string): Promise<string>;
69
+ /**
70
+ * Execute Python code in the remote workbench using COMPOSIO_REMOTE_WORKBENCH
71
+ */
72
+ executeWorkbench(code: string, options?: {
73
+ thought?: string;
74
+ currentStep?: string;
75
+ currentStepMetric?: string;
76
+ userId?: string;
77
+ }): Promise<{
78
+ success: boolean;
79
+ output?: unknown;
80
+ error?: string;
81
+ }>;
82
+ /**
83
+ * Execute bash commands in the remote sandbox using COMPOSIO_REMOTE_BASH_TOOL
84
+ */
85
+ executeBash(command: string, userId?: string): Promise<{
86
+ success: boolean;
87
+ output?: unknown;
88
+ error?: string;
89
+ }>;
90
+ }
91
+ /**
92
+ * Create a Composio client instance
93
+ */
94
+ export declare function createComposioClient(config: ComposioConfig): ComposioClient;