Building Integrations for Mitosis
Last updated: 2026-04-17
This guide walks you through creating, testing, and publishing a community integration for Mitosis. Integrations connect agents to external services — messaging platforms, APIs, developer tools, VPNs, and more.
How Integrations Work
When a user enables an integration:
- Credentials are stored securely on the server side
- Credentials are injected into agent pods automatically — agents see them as environment variables
- Agents use the credentials directly (API keys, tokens) or connect through a per-office proxy service
Agents don't need custom code to read integration credentials — they're just env vars.
Integration Types
Secret-only
User pastes a credential and it's done. Best for API keys, tokens, and simple auth. Examples: GitHub, Telegram, Slack, ElevenLabs.
Per-office service
User pastes a credential, then a proxy service starts for the colony. Use when the integration needs a running process. Examples: Tailscale (SOCKS5 proxy), Claude Code (OAuth proxy).
OAuth
User clicks "Connect" and authorizes via the provider. Use when the provider supports OAuth flows. Examples: Claude Code, OpenAI Codex, Google Workspace.
Most community integrations are secret-only — the user pastes an API key and agents get it as an env var.
Quick Start: Your First Integration
We'll build a simple integration that gives agents access to a hypothetical "Acme API" using an API key.
Step 1: Define the integration
Add your integration to the registry in src/lib/integrations/registry.ts:
{
id: 'acme',
name: 'Acme API',
description: 'Connect agents to the Acme API for data processing.',
icon: 'acme', // Add a matching icon in integration-node.tsx
category: 'services', // 'llm' | 'communication' | 'services'
aliases: ['acme-api'], // Search terms that resolve to this integration
verified: false, // true = shows purple checkmark (Mitosis-verified only)
capabilities: ['data_processing'],
channels: [], // Empty for tool-only integrations
wizard: 'guide', // 'guide' | 'interactive' | 'oauth' | 'auto'
guideFile: 'integrations/acme.md',
requiredSecrets: [
{
key: 'ACME_API_KEY',
label: 'API Key',
type: 'password',
required: true,
hint: 'Create an API key with read/write access',
helpUrl: 'https://acme.com/settings/api-keys',
},
],
agentEnvVars: ['ACME_API_KEY'],
officeLevel: true,
k8sSecretName: (colonyId) => `acme-${colonyId}`,
}
Step 2: Write the setup guide
Create public/integrations/acme.md:
# Connect Acme API
Agents can query, transform, and process data using the Acme API.
## Steps
1. Go to your Acme dashboard
2. Create an API key with read/write access
3. Paste it below
## What Agents Can Do
- Query datasets
- Run data pipelines
- Export results
## Notes
- Your API key is stored securely — agents access it as an env var.
- Usage is billed by Acme directly.
Step 3: Add an icon
In src/components/inception/dashboard/integration-node.tsx, import an icon and add it to the BRAND_ICONS map:
import { Database } from 'lucide-react';
const BRAND_ICONS = {
// ... existing icons ...
acme: Database,
};
Step 4: Register on the backend
In the office-manager repo, add your integration to the backend registry:
{
Name: "Acme API",
ID: "acme",
Status: "pending",
SecretName: fmt.Sprintf("acme-%s", officeID),
Capabilities: []string{"data_processing"},
AgentEnvVars: []string{"ACME_API_KEY"},
},
Step 5: Add to reserved keys (optional)
If agents shouldn't be able to override this env var via the Environment Secrets panel, add it to the reserved keys list in the colony-manager backend:
"ACME_API_KEY": true,
That's it. The existing GuideWizard, EnsureSecret, and ToggleAgent handlers do the rest.
Credential Fields
Each field in requiredSecrets becomes an input in the setup wizard.
key (string, required) — The env var name (e.g. ACME_API_KEY).
label (string, required) — Display label shown in the wizard (e.g. "API Key").
type ('text' or 'password', required) — Use password for secrets, text for non-sensitive values.
required (boolean, required) — Must be filled before saving.
hint (string, recommended) — Short help text displayed below the field.
helpUrl (string, strongly recommended) — Direct link to where the user creates or copies this credential. Renders as a clickable link next to the hint. Always include this — it takes users directly to the right page instead of making them search through a provider's settings.
helpLabel (string, optional) — Custom link text. Default: "Find it here".
Multi-Instance Integrations
Some integrations support multiple named instances per office — for example, a user might connect both a personal and a work GitHub account.
To enable this, set multiInstance: true in the registry and add an INSTANCE_LABEL field:
{
id: 'myservice',
multiInstance: true,
requiredSecrets: [
{ key: 'API_KEY', label: 'API Key', type: 'password', required: true },
{ key: 'INSTANCE_LABEL', label: 'Account Label', type: 'text', required: true,
hint: 'A short name for this account, e.g. "personal" or "work"' },
],
k8sSecretName: (colonyId, instanceLabel) =>
instanceLabel ? `myservice-${instanceLabel}-${colonyId}` : `myservice-${colonyId}`,
}
Each instance gets its own K8s secret and can be toggled independently per agent.
Per-Office Service Integrations
If your integration needs a running process (proxy, daemon, persistent connection), follow the per-office service pattern.
Create a provisioner in the colony-manager repo that manages these resources:
| Resource | Purpose |
|---|---|
| Deployment | Runs the service container (1 replica, Recreate strategy) |
| Service | ClusterIP for in-cluster access |
| PVC | Persistent state (optional) |
| Secret | Credentials |
Key functions to implement:
func Configure{Name}(image string) // Set image from config
func {Name}URL(namespace string) string // Return in-cluster URL
func (c *Client) Ensure{Name}(ctx context.Context, ns string) error // Create-or-update
func (c *Client) Teardown{Name}(ctx context.Context, ns string) error // Remove (retain PVC)
The service is not provisioned at office creation — it starts lazily when a user first enables the integration (in the ToggleAgent handler).
See the Tailscale integration in the colony-manager repo for a complete example.
Testing
Local testing
# Start the dev stack
make dev
# Set a secret via the colony-manager API
curl -X POST http://localhost:8080/api/v1/offices/{officeID}/integrations/acme/secret \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"secretName":"acme-{officeID}","data":{"ACME_API_KEY":"test-key-123"}}'
# Enable on an agent
curl -X POST http://localhost:8080/api/v1/offices/{officeID}/integrations/acme/agents/{agentName} \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"enabled":true,"secretName":"acme-{officeID}"}'
# Verify the agent has the env var
mi agents exec <colonyId> <agentName> -- env | grep ACME
Dashboard testing
- Navigate to the Integrations panel in your office dashboard
- Find your integration in the list
- Click it → fill in credentials → Save
- Toggle it on for an agent
- Verify via the agent's terminal:
env | grep ACME
Checklist
- Integration appears in the Integrations panel
- Guide markdown loads and renders correctly
-
helpUrllinks open the correct page - Saving credentials shows success
- Toggling on an agent adds the secret to the pod
- Agent can read the env var
- Toggling off removes the env var from the pod
- Re-saving credentials updates the existing secret (idempotent)
- For per-office services: proxy pod starts on first enable, stops on teardown
Publishing
Community integrations are submitted as pull requests to the website and office-manager repos.
Your PR should include:
-
Website repo:
- Registry entry in
src/lib/integrations/registry.ts - Icon in
src/components/inception/dashboard/integration-node.tsx - Guide markdown in
public/integrations/{id}.md
- Registry entry in
-
Office-manager repo:
- Backend registration in the integrations handler
- Reserved keys in the env handler (if applicable)
- For per-office services: a provisioner module + tests
-
Description explaining what the integration does, what env vars it injects, and any security considerations.
Verified integrations (purple checkmark) are reviewed and maintained by the Mitosis team. Community integrations are welcome and encouraged — if you build something useful, we'll work with you to get it verified.
Manifest v2 — Composable Layers
Integrations can declare up to 9 composable layers beyond the basic requiredSecrets + agentEnvVars. All layers are optional and backwards-compatible — existing integrations keep working unchanged.
| Layer | Field | What it does |
|---|---|---|
| 1. Tools | tools | OpenClaw gateway plugins, MCP servers, SDK extensions |
| 2. CLI Installs | cliInstalls | apt/npm/pip packages and static binaries installed into agent pods |
| 3. Credential Files | credentialFiles | Config files rendered from templates into the agent's persistent volume |
| 4. Shared Drive Folder | sharedDrive | Permissioned folder at /shared/files/_integrations/<id>/ — only enabled agents can access |
| 5. Colony Database | database | Permissioned tables in the colony postgres — only enabled agents get credentials |
| 6. Task Templates | taskTemplates | Tasks auto-created on enable, or recurring on a cron schedule |
| 7. Member Controls | members | Required roles, max agent count, per-agent config overrides |
| 8. Colony Container | colonyContainer | Per-office microservice (Deployment + Service + optional PVC) |
Composability
Integrations can declare relationships with other integrations:
| Field | Type | Description |
|---|---|---|
dependsOn | string[] | Integrations that must be configured first |
provides | string[] | Capabilities this integration provides (for dependency resolution) |
conflicts | string[] | Integrations that cannot coexist |
composedWith | string[] | Integrations that work better together (soft recommendation) |
Example: Full Manifest
{
id: 'acme',
name: 'Acme API',
version: '1.0.0',
category: 'services',
// ... basic fields ...
// Layer 1: MCP server for tool use
tools: {
mcpServers: [{
name: 'acme-mcp',
command: 'npx',
args: ['-y', '@acme/mcp-server'],
env: { ACME_API_KEY: '${ACME_API_KEY}' },
}],
},
// Layer 2: CLI tool
cliInstalls: {
npm: ['@acme/cli'],
},
// Layer 4: Shared folder for cached data
sharedDrive: {
subdirectories: ['cache', 'output'],
},
// Layer 5: Database tables for state
database: {
migrations: ['001_create_tables.sql'],
},
// Composability
provides: ['data_processing'],
composedWith: ['github'],
}
For full manifest type definition, see IntegrationDef in src/lib/integrations/registry.ts.
Looking for the docs index? Browse all guides.