feat(connectors): implement GET + POST /api/connectors/actions

Merged
SW
6mo ago
+1358-10

Summary

Implements the contract from recoupable/docs PR #167 (merged). Gives sandbox agents (open-agents) HTTP access to the connector action layer that the chat agent uses internally — sandbox curl + Bearer token can now list and execute the same connector tools (Gmail, Sheets, TikTok, etc.) the chat side has been using through lib/composio/toolRouter.

This is PR 2 of 3 — implementation. PR 3 (skills) updates recoup-api/SKILL.md to point sandbox agents at these endpoints.

Endpoints

  • GET /api/connectors/actions — lists every executable action across the account's supported toolkits. Each action returns slug (UPPERCASE_SNAKE_CASE), name, description, parameters (JSON Schema), connectorSlug (parent toolkit, derived from slug prefix), isConnected (derived from parent toolkit's connection state). Optional account_id query param mirrors GET /api/connectors.
  • POST /api/connectors/actions — executes an action by slug with parameters. Composio validates the parameters against its cached schema and checks connection state before invoking; we surface the slug-not-found case as a typed ConnectorActionNotFoundError mapped to 404.

Both reuse validateAuthContext + checkAccountAccess — same auth pattern as the existing /api/connectors/{list,authorize,disconnect} family. No new auth surface.

Built TDD

Per api/CLAUDE.md's TDD requirement, each new file has its test written first, run failing (red), then implemented to green. 40 new tests across 8 new test files; all 113 connectors-suite tests pass.

FileNew tests
validateGetConnectorActionsQuery.test.ts3
validateExecuteConnectorActionBody.test.ts8
validateGetConnectorActionsRequest.test.ts5
validateExecuteConnectorActionRequest.test.ts5
getConnectorActions.test.ts5
executeConnectorAction.test.ts5
getConnectorActionsHandler.test.ts4
executeConnectorActionHandler.test.ts5

Files

app/api/connectors/actions/
└── route.ts                        # Next.js route — GET + POST + OPTIONS

lib/composio/connectors/
├── getConnectorActions.ts          # Composio catalog fetch
├── executeConnectorAction.ts       # Composio execute + ConnectorActionNotFoundError
├── getConnectorActionsHandler.ts   # GET orchestrator → { success, actions }
├── executeConnectorActionHandler.ts# POST orchestrator → { success, result, executedAt }
├── validateGetConnectorActionsQuery.ts
├── validateGetConnectorActionsRequest.ts
├── validateExecuteConnectorActionBody.ts
└── validateExecuteConnectorActionRequest.ts

Reuses SUPPORTED_TOOLKITS (googlesheets, googledrive, googledocs, tiktok, instagram) and buildAuthConfigs() from the existing connector code — same toolkit set as the chat agent.

Response shapes

Match the project's flat-response convention:

// GET response
{ "success": true, "actions": [ { "slug": "GMAIL_FETCH_EMAILS", ... } ] }

// POST success
{ "success": true, "result": { ...action's result... }, "executedAt": "2026-04-27T..." }

Error mapping

  • 400 — invalid body / query (Zod validators).
  • 401 — missing / invalid auth (handled by validateAuthContext).
  • 403 — token valid but no access to specified account_id (handled by checkAccountAccess).
  • 404 — actionSlug not in the account's catalog (typed ConnectorActionNotFoundError).
  • 500 — generic upstream / unexpected (catch-all).

The doc spec also documents 409 (not connected) and 502 (upstream failure). These currently bucket into 500 with the underlying error message — granular mapping is deferred to a follow-up once we see real Composio error shapes in QA. The contract is a superset; we never promise to emit 409 vs 500 for a given case, only that those codes mean those things if emitted.

Pre-existing typecheck noise

pnpm tsc --noEmit reports a few errors in lib/tasks/__tests__/ and lib/trigger/__tests__/ that exist on test already. The 3 mock-typing errors in my new tests match an identical pattern in the pre-existing getConnectors.test.ts (line 17) — codebase has tolerated this pattern. Tests pass; lint passes.

Test plan

  • pnpm test lib/composio/connectors/__tests__/ — 113/113 pass
  • pnpm lint:check — clean
  • Smoke test in preview deploy: curl -H "Authorization: Bearer $TOKEN" $PREVIEW_URL/api/connectors/actions returns the catalog
  • Execute a simple action (e.g. GMAIL_FETCH_EMAILS) end-to-end from a sandbox

Order of merge

  1. ✅ recoupable/docs PR #167 — contract (merged).
  2. This PR — implementation against contract.
  3. recoupable/skills PR (TBD) — recoup-api/SKILL.md adds a "Connector actions" section pointing sandbox agents at these endpoints.

🤖 Generated with Claude Code


Summary by cubic

Adds GET and POST /api/connectors/actions so sandbox agents can list and run connector actions. Execute path now uses the same merged toolkits (customer > artist > shared) as the catalog, so anything listed is runnable.

  • New Features

    • GET /api/connectors/actions: { success, actions } where each action has slug, name, description, parameters (JSON Schema), connectorSlug, isConnected. Optional account_id query. Catalog mirrors chat via merged toolkits.
    • POST /api/connectors/actions: run by actionSlug with parameters (optional account_id in body); returns { success, result, executedAt }. Unknown slugs → 404. Reuses existing auth + access checks; CORS OPTIONS included.
  • Bug Fixes

    • Execute path now resolves tools via the merged catalog (customer > artist > shared), matching GET; fixes 404s when POSTing actions returned by GET.
    • toJsonSchema converts Composio tool inputSchema to JSON Schema for Zod v4 and v3 (via zod-to-json-schema) so no Zod internals leak into responses.

Summary by CodeRabbit

  • New Features
    • Added GET endpoint to retrieve available connector actions with their parameters and descriptions
    • Added POST endpoint to execute connector actions with full authentication and authorization support
    • Implemented comprehensive error handling with appropriate HTTP status codes
    • Added CORS support for both new endpoints