Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 41 additions & 27 deletions .specs/kiloclaw-composio.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,71 +2,85 @@

## Role of This Document

This spec defines the security and product rules for user-provided Composio CLI credentials configured in KiloClaw Settings. Managed Composio identity provisioning and managed connection onboarding are retired and are not supported behavior. Removing retired managed persistence does not alter this manual Settings contract.
This spec defines the security and product rules for the user-provided Composio credential configured in KiloClaw Settings. Managed Composio identity provisioning and managed connection onboarding are retired and are not supported behavior. Removing retired managed persistence does not alter this manual Settings contract.

It deliberately does not prescribe implementation details such as endpoint names, column layouts, or controller helper structure.

## Status

Draft -- created for managed Composio onboarding in PR #3348 on 2026-05-20.
Updated 2026-05-27 -- reduced to manual Settings configuration after retiring managed onboarding and storage.
Updated 2026-07-22 -- switched the supported surface from Composio CLI sign-in to Composio Connect over MCP.

## Conventions

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC 2119] [RFC 8174] when, and only when, they appear in all capitals, as shown here.

## Definitions

- **Composio CLI credentials**: The user API key and organization identifier required to sign the `composio` CLI into a user's Composio account or organization.
- **Manual Composio configuration**: User-provided Composio CLI credentials saved through KiloClaw Settings and injected into that user's OpenClaw instance.
- **OpenClaw instance**: The provider-backed KiloClaw environment where OpenClaw and the `composio` CLI run.
- **Consumer key**: The `ck_`-prefixed credential a user copies from the AI Clients page of the Composio dashboard. It authenticates against Composio Connect and is not interchangeable with the CLI's user API key (`uak_`) or a project API key (`ak_`).
- **Composio Connect**: Composio's hosted MCP server, which exposes toolkit capabilities as MCP tools to any client presenting a consumer key.
- **Manual Composio configuration**: A user-provided consumer key saved through KiloClaw Settings and injected into that user's OpenClaw instance.
- **Legacy CLI credentials**: `COMPOSIO_USER_API_KEY` and `COMPOSIO_ORG` values configured before this surface existed, or created by a user running `composio login` inside their own instance.
- **OpenClaw instance**: The provider-backed KiloClaw environment where OpenClaw runs.

## Overview

KiloClaw supports Composio only as explicitly user-provided Settings secrets. A user may enter Composio CLI credentials, which are validated, encrypted, transported through the existing instance secret pipeline, and used by the controller to make the Composio CLI available inside that user's instance.
KiloClaw supports Composio only as an explicitly user-provided Settings secret. A user may enter a consumer key, which is validated, encrypted, transported through the existing instance secret pipeline, and written by the controller into the instance's OpenClaw configuration as a remote MCP server definition. Composio's tools then reach the agent over HTTP; KiloClaw installs and runs nothing on the user's behalf.

Toolkit authorization (Gmail, Calendar, and so on) happens entirely in the Composio dashboard. KiloClaw MUST NOT attempt to broker, initiate, or store those connections.

Kilo MUST NOT provision managed Composio identities, create managed Connect Link onboarding flows, store managed Composio credential state, or inject operator-owned or previously managed credentials into instances.

## Rules

### Manual Configuration

1. Manual Composio configuration MUST be opt-in. An instance without both required Composio fields MUST continue to boot without Composio CLI sign-in.
2. The system MUST validate manual Composio fields according to the secret catalog contract before saving or provisioning them. If either required Composio field is supplied during provision, both MUST be supplied together.
3. Manual Composio credentials MUST be treated as user-provided secrets. Both the user API key and organization value MUST be encrypted before reaching the KiloClaw Worker and MUST use the existing encrypted instance-secret transport pipeline.
4. Manual Composio fields MAY remain configurable through Settings and MAY be updated or removed through the normal instance secret update path.
5. Kilo MUST NOT rotate, revoke, claim, share, or otherwise manage manually provided Composio credentials unless a future supported flow explicitly requests that behavior.
6. Manual personal Composio credentials MUST NOT be reused for an organization instance unless the user explicitly configures them in that organization context.
1. Manual Composio configuration MUST be opt-in. An instance without a consumer key MUST continue to boot with no Composio server defined.
2. The system MUST validate the consumer key according to the secret catalog contract before saving or provisioning it.
3. Consumer key validation SHOULD stay permissive beyond the credential family prefix. Composio performs no prefix or length check of its own, so validation stricter than the documented shape risks rejecting a valid credential.
4. The consumer key MUST be treated as a user-provided secret, encrypted before reaching the KiloClaw Worker, and carried by the existing encrypted instance-secret transport pipeline.
5. The consumer key MAY be updated or removed through the normal instance secret update path.
6. Kilo MUST NOT rotate, revoke, claim, share, or otherwise manage a manually provided Composio credential unless a future supported flow explicitly requests that behavior.
7. A personal consumer key MUST NOT be reused for an organization instance unless the user explicitly configures it in that organization context.

### Removed Managed Behavior

7. Kilo MUST NOT create new managed Composio identities, managed connected-account onboarding flows, Connect Links for managed onboarding, or managed credential injection for KiloClaw.
8. Kilo MUST NOT fall back from missing manual Composio credentials to any operator-owned, shared, historical, or managed credential.
9. New instances and Settings updates MUST NOT create retired managed-onboarding metadata for manual Composio configuration.
10. Direct Google Calendar onboarding, when offered, is independent of Composio and MUST NOT depend on retired managed Composio state.
8. Kilo MUST NOT create new managed Composio identities, managed connected-account onboarding flows, Connect Links for managed onboarding, or managed credential injection for KiloClaw.
9. Kilo MUST NOT fall back from a missing consumer key to any operator-owned, shared, historical, or managed credential.
10. New instances and Settings updates MUST NOT create retired managed-onboarding metadata for manual Composio configuration.
11. Direct Google Calendar onboarding, when offered, is independent of Composio and MUST NOT depend on retired managed Composio state.

### Instance CLI Sign-In
### Instance Configuration

11. The OpenClaw instance MAY contain the Composio CLI when no Composio credentials are configured.
12. When valid manual Composio credentials are present, the controller SHOULD sign the CLI in during bootstrap so `composio` commands work without interactive browser login.
13. Composio CLI sign-in MUST be best-effort and MUST NOT prevent controller startup unless a future product contract makes it required.
14. If sign-in uses a subprocess, the implementation MUST invoke a direct executable rather than a shell and MUST suppress logs containing credentials.
15. Any Composio CLI state files written by the controller MUST use owner-only permissions and remain inside the instance user's Composio configuration directory.
16. Credentials used only for CLI sign-in MUST NOT remain unnecessarily available to unrelated child processes.
12. When a consumer key is present, the controller MUST define Composio Connect as a remote MCP server in the instance's OpenClaw configuration, replacing any existing definition of that server outright. It MUST NOT install software, spawn a login subprocess, or perform any network call on the user's behalf to establish the connection. Carrying fields over from a previous definition risks retaining an authentication mode that suppresses the configured credential.
13. When no consumer key is present, the controller MUST remove the server definition it manages, because instance configuration persists across redeploys and a stale definition would otherwise outlive the credential's removal from Settings.
14. Removal MUST be limited to a definition KiloClaw explicitly marked as managed when it wrote it. Ownership MUST NOT be inferred from a definition's endpoint, transport, headers, or any other value published by Composio, because a user configuring the same product by hand produces an identical definition. An unmarked Composio server MUST be left intact.
15. Configuring Composio MUST NOT prevent controller startup. An unreachable or unauthorized endpoint surfaces at tool-call time and MUST NOT be treated as a boot failure.
16. The instance MAY continue to contain the Composio CLI, and legacy CLI credentials MUST continue to reach the instance so that a sign-in a user performed themselves is not broken by an upgrade. Retiring a credential's Settings field MUST NOT downgrade how that credential is carried: a retired credential env var name MUST remain classified sensitive so its value is still encrypted in transport rather than written to the provider's plaintext environment.
17. Agent-facing documentation MUST describe the MCP surface and MUST NOT instruct the agent to sign the CLI in, because doing so cannot change which tools the configured credential reaches.

### Data Protection and Logging

17. Logs, analytics, audit records, Sentry events, command output, and user-facing errors MUST NOT contain raw Composio credentials, OAuth tokens, or generated login commands containing credential material.
18. Manual Composio secrets MUST follow the normal KiloClaw secret encryption, transport, update, and deletion rules.
18. Logs, analytics, audit records, Sentry events, command output, and user-facing errors MUST NOT contain raw Composio credentials, OAuth tokens, or generated commands containing credential material.
19. Manual Composio secrets MUST follow the normal KiloClaw secret encryption, transport, update, and deletion rules.

## Error Handling

1. If manual Composio credentials are missing or incomplete, the controller MUST skip Composio CLI sign-in and continue startup.
2. If manual Composio credential validation fails, the save or provision request MUST fail before transporting invalid credentials to the Worker.
3. If Composio CLI sign-in fails, the controller MUST log a sanitized failure and SHOULD continue startup in a usable state.
1. If no consumer key is configured, the controller MUST continue startup with no Composio server defined.
2. If consumer key validation fails, the save or provision request MUST fail before transporting the invalid credential to the Worker.
3. If Composio Connect is unreachable or rejects the credential, the failure MUST surface to the agent at tool-call time and MUST NOT degrade the instance.

## Changelog

### 2026-07-22 -- Composio Connect over MCP

- Replaced the CLI user API key and organization fields with a single consumer key field.
- Defined Composio Connect as a remote MCP server written into instance configuration, replacing controller-run CLI sign-in as the supported path.
- Scoped managed removal to definitions KiloClaw marks as its own, so hand-configured Composio servers are not deleted.
- Kept legacy CLI credentials flowing to instances, and the CLI installed, so existing manual sign-ins survive.
- Retained the two legacy CLI env var names as always-sensitive so a value under either stays encrypted in transport even though the fields left the catalog.

### 2026-05-27 -- Retained manual configuration only

- Removed managed identity provisioning, managed Connect Link onboarding, managed persistence, and instance-source tracking from supported behavior.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const DESCRIPTION_MAP: Record<string, string> = {
agentcard: 'Give your bot virtual debit cards for spending',
onepassword: 'Look up credentials and manage vault items via the op CLI',
'brave-search': 'Add a Brave Search API key for web search',
composio: 'Sign the Composio CLI into this sandbox',
composio: 'Connect your Composio toolkits',
};

export function getDescription(entryId: string): string {
Expand Down
44 changes: 25 additions & 19 deletions apps/web/src/lib/kiloclaw/provision-secrets.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,43 @@ describe('encryptProvisionSecretsForWorker', () => {
it('maps valid manual Composio secret keys to worker env var names before encrypting', () => {
expect(
encryptProvisionSecretsForWorker({
composioUserApiKey: 'uak_manual_credential_123',
composioOrg: 'org-1',
composioConsumerKey: 'ck_manual_credential_123',
CUSTOM_SECRET: 'kept',
})
).toEqual({
COMPOSIO_USER_API_KEY: 'encrypted:uak_manual_credential_123',
COMPOSIO_ORG: 'encrypted:org-1',
COMPOSIO_CONSUMER_KEY: 'encrypted:ck_manual_credential_123',
CUSTOM_SECRET: 'encrypted:kept',
});
});

it('keeps manual Composio validation when secrets are passed during provision', () => {
expect(() =>
encryptProvisionSecretsForWorker({
composioUserApiKey: 'uak_short',
composioOrg: 'org-1',
composioConsumerKey: 'ck_short',
})
).toThrow('Composio user API keys start with uak_');
).toThrow('Composio consumer keys start with ck_');
});

const partialComposioCredentialPairs: Array<Record<string, string>> = [
{ composioUserApiKey: 'uak_manual_credential_123' },
{ composioOrg: 'org-1' },
];
it('rejects a Composio CLI user API key, which belongs to a different surface', () => {
expect(() =>
encryptProvisionSecretsForWorker({
composioConsumerKey: 'uak_manual_credential_123',
})
).toThrow('Composio consumer keys start with ck_');
});

it.each(partialComposioCredentialPairs)(
'rejects a partial manual Composio credential pair during provision',
secrets => {
expect(() => encryptProvisionSecretsForWorker(secrets)).toThrow(
'Composio requires all fields to be set together'
);
}
);
// Credentials configured before the Composio Connect switch keep flowing to
// the instance as ordinary custom secrets, so a stale CLI login is not
// silently broken by an upgrade.
it('passes legacy Composio CLI env vars through untouched', () => {
expect(
encryptProvisionSecretsForWorker({
COMPOSIO_USER_API_KEY: 'uak_manual_credential_123',
COMPOSIO_ORG: 'org-1',
})
).toEqual({
COMPOSIO_USER_API_KEY: 'encrypted:uak_manual_credential_123',
COMPOSIO_ORG: 'encrypted:org-1',
});
});
});
15 changes: 1 addition & 14 deletions apps/web/src/lib/kiloclaw/provision-secrets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,9 @@ import {
} from '@kilocode/kiloclaw-secret-catalog';
import { encryptKiloClawSecret } from '@/lib/kiloclaw/encryption';

const COMPOSIO_SECRET_FIELD_KEYS = ['composioUserApiKey', 'composioOrg'] as const;

function hasComposioProvisionSecrets(secrets: Record<string, string>): boolean {
return COMPOSIO_SECRET_FIELD_KEYS.some(key => secrets[key] !== undefined);
}
const COMPOSIO_SECRET_FIELD_KEYS = ['composioConsumerKey'] as const;

function validateComposioProvisionSecrets(secrets: Record<string, string>): void {
if (!hasComposioProvisionSecrets(secrets)) return;
const hasAllFields = COMPOSIO_SECRET_FIELD_KEYS.every(key => secrets[key] !== undefined);
if (!hasAllFields) {
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'Composio requires all fields to be set together',
});
}

for (const key of COMPOSIO_SECRET_FIELD_KEYS) {
const value = secrets[key];
if (value === undefined) continue;
Expand Down
Loading
Loading