dánwòdánwò

AI

Composio

Composio's toolkits, tool execution, connected accounts with hosted connect links, and triggers, with tools that act on danwo's Google, Slack, GitHub and Microsoft emulators.

danwo's Composio emulator answers backend.composio.dev and its hosted connect pages on connect.composio.dev. @composio/core works against it unchanged: your agent lists tools, connects a user's accounts and executes tools.

What makes it more than a stub is routing to other emulators. Give it danwo's Google, Slack, GitHub or Microsoft service as a backend, and a user connects Gmail on the Google emulator's consent page, and GMAIL_SEND_EMAIL lands in the Google emulator's mailbox, where a test can read it.

Set up

List the backends before Composio, and pass them in backends:

danwo.config.ts
import { appEnvironment, composioService, defineConfig, googleService } from "@danwo/sdk"

const url = "http://localhost:3000"

export default defineConfig({
  testDir: "tests",
  readiness: { mode: "page+backend", settle: true },
  environment: () => {
    const google = googleService({
      seed: { users: [{ email: "ada@example.com", name: "Ada Lovelace" }] },
    })

    return appEnvironment({
      app: { command: "npm run dev", url, env: { COMPOSIO_API_KEY: "danwo-composio-key" } },
      services: [
        google,
        composioService({
          backends: [google],
          seed: {
            apiKeys: ["danwo-composio-key"],
            authConfigs: [{ toolkit: "gmail", id: "ac_gmail" }],
          },
        }),
      ],
    })
  },
})

Toolkits without a backend connect on Composio's own page and answer from seeded results or sample data.

Seed it

FieldWhat it seeds
apiKeysThe project's API keys.
toolkits, toolsExtra toolkits and tools beside the built-in catalogue, with input schemas.
authConfigsAuth configs by toolkit: Composio-managed or your own credentials and scopes.
connectedAccountsAccounts already connected for a user, ACTIVE or EXPIRED.
triggersTrigger instances on a connected account.
webhookThe project's webhook subscription: URL, secret and events.
resultsCanned results for a tool, optionally only for matching arguments, or an error.

Use it in a test

Connect Gmail as the user, ask the agent to send an email, then read the Google emulator's mailbox:

tests/agent-email.danwo.ts
import {
  type ComposioFixtures,
  composioProject,
  type GoogleFixtures,
  gmailMailbox,
  test as base,
} from "@danwo/sdk"

const test = base.extend<ComposioFixtures & GoogleFixtures>()

test("the agent emails the customer", async ({ app, screen, expect, composio, google }) => {
  await app.open("/integrations")
  await screen.getByRole("button", { name: "Connect Gmail" }).click()
  await screen.getByRole("button", { name: "Continue as Ada Lovelace" }).click()

  await app.open("/agent")
  await screen.getByLabel("Ask").fill("Email bob@example.com that the order shipped")
  await screen.getByRole("button", { name: "Send" }).click()
  await expect(screen.getByText("Email sent")).toBeVisible()

  const [execution] = composioProject(composio).executions()
  const [sent] = gmailMailbox(google, "ada@example.com").sent()

  expect(execution?.tool).toBe("GMAIL_SEND_EMAIL")
  expect(execution?.source).toBe("backend")
  expect(sent?.to).toBe("bob@example.com")
})
HelperWhat it's for
composioProject(composio).executions()Every tool run, and whether a seed, a backend or sample data answered it.
composioProject(composio).accounts()The connected accounts.
composioProject(composio).fire(…)Fire a trigger, as the toolkit would.
composioProject(composio).expire(id)Expire a connected account.
composioTools(composio).handle(…)Answer a tool from the test, before any seed or backend.

Pair it with the model API emulator to script the tool calls the model makes.

What's covered

AreaCovered
CatalogueToolkits, tools and trigger types.
ExecutionRunning tools, and the proxy call.
AccountsAuth configs, connected accounts, connect links and the hosted page.
TriggersTrigger instances, and firing them.
WebhooksThe webhook subscription, its event types and secret.
Backed toolsGmail, Calendar, Drive, Slack, GitHub and Outlook tools act on their emulators.

The backed tools:

ToolkitTools
GmailGMAIL_SEND_EMAIL, GMAIL_FETCH_EMAILS, GMAIL_CREATE_EMAIL_DRAFT
Calendar and DriveGOOGLECALENDAR_CREATE_EVENT, GOOGLECALENDAR_EVENTS_LIST, GOOGLEDRIVE_FIND_FILE
SlackSLACK_SEND_MESSAGE, SLACK_LIST_ALL_CHANNELS
GitHubGITHUB_CREATE_AN_ISSUE, GITHUB_GET_A_REPOSITORY
OutlookOUTLOOK_SEND_EMAIL, OUTLOOK_LIST_MESSAGES

Faults

CallFaults the matrix tries
POST /tools/execute/:slug429, 503, 408, 422 for an expired account, a 200 with successful: false, a 30-second delay, 500, connection reset, answer lost after the tool ran
A connect link429, 500, connection reset
A read500, connection reset
Every webhook deliveryarrives twice, arrives 10 minutes late, forged signature, 1 hour stale

Webhooks

Trigger events and account expiries go to the webhook subscription, signed with webhook-id, webhook-timestamp and webhook-signature.

Fidelity

Live, reads only. danwo fidelity composio runs 3 scenarios against a real project: errors, the catalogue, and auth configs and connected accounts. All 3 match.

Not covered yet

  • Most toolkits' tools act on sample data: only the tools above reach a backend
  • MCP servers hosted by Composio
  • Custom tools defined in code on Composio's side

Next

On this page

Run it on every pull request

A GitHub check and one comment per pull request, with the flight records attached.

Set up CI