Composio plugin
connector-composio is an ordinary OHarness RuntimePlugin. It uses Composio's official REST API for account inspection, schema discovery and tool execution. It does not introduce MCP, another Agent loop, a second plugin host, or an SDK dependency. createConnectorPlugin remains the vendor-neutral adapter helper.
Scope and verification
- Implemented: explicit tool allowlists, account/user binding, schema conversion, version pinning, cancellation, response-size limits and OHarness permission gates.
- Implemented: explicit human-operated hosted auth-link creation and account status.
- Not implemented: Pipedream, webhooks, shared-account ACLs, automatic OAuth callback identity verification in OHarness Cloud, remote plugin installation, file upload/download automation or runtime hot reload.
- Tests use mocked HTTP responses and require no credentials. A live account smoke test must be performed separately with your own credentials and consent.
Composio recommends Sessions for new agent integrations and labels direct execution as legacy. This first adapter intentionally uses the still-documented direct endpoints to keep the existing OHarness tool registry and per-tool permissions in control. Only explicitly selected tools are exposed, rather than a generic router capable of invoking an arbitrary action. See the official direct execution guide.
This direct adapter is for explicitly configured development/self-hosted use. In the hosted product, the platform Composio key belongs to Cloud, not each client. Use the [Cloud connector](cloud-connectors.md) for the hosted product: it provides authorization cards, server-verified user binding and task continuation.
1. Set the project API key
Set COMPOSIO_API_KEY in the environment of the process running OHarness. Do not put it in your repository, chat messages or plugin JSON. The config may name a different environment variable via apiKeyEnv.
The transport only sends this key to https://backend.composio.dev, refuses HTTP redirects and does not accept a configurable API origin. All remote calls are explicit client requests; constructing/importing the plugin makes no call.
2. See what is already connected
Every toolkit entry in the configuration needs a connectedAccountId, and the first question is whether you already have one:
npm run composio:auth -- list --user YOUR_USER_ID
Read-only, scoped to that user, and paginated — pass --toolkit SLUG to narrow it, --limit N (1-100, default 50) to size the page, and --cursor with the cursor a previous call returned. It prints id, toolkit, status and disabled per account and nothing else: the upstream rows carry credential and state fields, and this command drops them the same way account inspection does.
An account listed under a different user is refused rather than hidden, since a response mixing users is not one to trust for the rows that did match.
3. Connect an account
If the list is empty, or the toolkit you need is missing from it, create an auth configuration for the app in Composio and then explicitly request a hosted Connect Link from the repo:
npm run composio:auth -- link --user YOUR_USER_ID --auth-config ac_YOUR_AUTH_CONFIG
The command performs a remote POST and prints redirectUrl, connectedAccountId and an optional expiry. Open that URL yourself and complete consent. Treat it as a private authorization link: do not share it with another user. The command does not open a browser, approve access, save configuration, or expose a link-creation tool to the Agent.
Inspect the resulting connection with a read-only request:
npm run composio:auth -- status --user YOUR_USER_ID --account ca_YOUR_ACCOUNT
Continue when the status is ACTIVE, the toolkit is correct and disabled is false. Use the same user ID for linking and execution. The adapter deliberately rejects an account belonging to a different user, even if the project API key could access it. Account inspection never returns credential/state fields.
For a multi-user hosted product, derive userId from authenticated application state and create appropriately isolated Harness instances. Do not accept it as model input. Composio's optional callback identity verification requires an authenticated HTTPS verifier in your application; this local adapter does not implement that server. See the official connection and callback identity documentation.
4. Enable the plugin
Build the workspace (npm run build) and add an entry to your user OHarness plugin file, normally ~/.oharness/plugins.json (or $OHARNESS_HOME/plugins.json). Replace the module path, user ID and account ID; do not copy placeholders as-is.
{
"runtimePlugins": [
{
"id": "connector-composio",
"module": "/absolute/path/to/OHarness/packages/engine/dist/runtime-plugins/composio/index.js",
"enabled": true,
"required": false,
"config": {
"userId": "YOUR_USER_ID",
"apiKeyEnv": "COMPOSIO_API_KEY",
"timeoutMs": 30000,
"toolkits": [
{
"slug": "gmail",
"connectedAccountId": "ca_YOUR_ACCOUNT",
"version": "latest",
"tools": ["GMAIL_GET_PROFILE"]
}
]
}
}
]
}
required: false leaves OHarness usable if this optional connector cannot start; the failure is visible in /plugins and Web's plugin list. Set it true only if startup must fail without the connector. Project config cannot enable executable plugins or replace their trusted account configuration.
For embedding, use the same implementation directly:
import { Harness, composioPlugin, jsonlAuditPlugin } from "@oharness/engine";
const harness = await Harness.create({
runtimePlugins: [
{
plugin: composioPlugin,
config: {
userId: authenticatedUserId,
toolkits: [{
slug: "gmail", connectedAccountId: approvedAccountId,
version: "latest", tools: ["GMAIL_GET_PROFILE"],
}],
},
},
{ plugin: jsonlAuditPlugin, config: { path: "/absolute/path/to/audit.jsonl" } },
],
});
// Use the existing Session / Agent API, then await harness.close().
Execution semantics
- Startup verifies each configured account belongs to the configured user, has the configured toolkit and is active/not disabled.
- Only named tool slugs are fetched; at most 40 tools across 20 toolkits.
- The returned slug/toolkit must match the allowlist.
latestis resolved at startup to a concrete dated version, reused for execution. A configured dated version must match the returned schema version exactly. - Tools are registered as
composio__SLUG. Names longer than 64 characters are shortened with a stable hash suffix. The exact names appear in ToolRegistry. - Calls go through the normal OHarness permission engine. All Composio tools have
readOnly: falseandsessionLocal: false, even remote read operations. Approval is skipped only when your normal explicit permission policy permits it. - Before each execution, account ownership/status/toolkit are checked again. The POST envelope uses the trusted user/account and pinned version; model parameters are nested under
argumentsand cannot replace those fields. - Successful data is converted to a ToolResult and enters the ordinary Agent flow and execution audit. HTTP/API failures become tool errors.
Tool input must be an object. Detailed argument-schema validation is performed by Composio; the returned JSON Schema is provided to the model. Only explicit tool implementations are supported, not proxy execution, custom auth overrides, natural-language execution or arbitrary remote URLs. No local files are read or uploaded by this adapter.
No HTTP call is automatically retried. A cancelled/failed POST may already have performed the remote action: inspect the external service or Composio log before retrying. Per-request timeout defaults to 30 seconds and is configurable from 100 ms to 120 seconds. Responses are capped at 2 MiB. Raw error bodies and API keys are not forwarded to logs; success data remains sensitive application data and is visible to the Agent as intended.
The first account/metadata requests happen when the plugin is enabled at boot; initialization does not create a new account or execute any allowlisted action.
Official API contract used
The adapter targets the documented /api/v3 routes on backend.composio.dev. These were checked against the official documentation on 2026-09-02; HTTP contract tests are not proof of live account authorization or vendor availability.