Write a native integration when an app needs more than the generic entry: triggers for workflows, custom tools, or guidance about how its API behaves. Everything reads the merged list through
all_integrations() in oauth_config.py. Never iterate OAUTH_INTEGRATIONS directly, because that misses the instance toolkits.
1. Declare the integration
Add anOAuthIntegration to OAUTH_INTEGRATIONS. Todoist is a compact example to copy:
idis the integration id everywhere: in connect URLs, in stored auth configs and in users’ connections. Use the lowercase Composio toolkit slug. If an instance admin already enabled that toolkit from the catalog, your code entry takes it over on the next boot, and their stored auth config and users’ connections keep working.composio_config.auth_config_idis GAIA Cloud’s auth config. Self-hosted instances never use it: their admin sets one up in Settings → Integrations setup. Until GAIA Cloud has one, ship the entry withavailable=False.destructive_toolslists the tool slugs that need approval (apps/api/app/constants/hil_destructive_tools.py). Leave itNoneonly if nobody has reviewed the tools. GAIA then asks an LLM classifier for every call, which fails closed.
2. Prompt, memory and content
- Prompt. Add
<NAME>_AGENT_SYSTEM_PROMPT = BASE_SUBAGENT_PROMPT.format(...)inapps/api/app/agents/prompts/subagent_prompts.py. Describe the domain and the API’s quirks, not generic agent behaviour: the base prompt already covers that. - Memory. Add
<NAME>_MEMORY_PROMPTinapps/api/app/agents/prompts/memory_prompts.pyif conversations with this app reveal durable facts worth remembering. - Content. Add the marketplace page content (use cases, how it works, FAQs) in
apps/api/app/config/oauth_content.py. - Icon. Add the logo to
libs/shared/ts/src/icons/integration-logos.tsand an entry intool-icon-config.ts. Instance toolkits use Composio’s logo URL instead.
3. Custom tools (optional)
Composio’s own tools load automatically fortool_space. Add custom tools when an app needs a better shape, for example one call that gathers a day’s context. They are Composio custom tools: see apps/api/app/agents/tools/integrations/todoist_tool.py and register them in apps/api/app/services/composio/custom_tools/registry.py. Put the most-used tools in auto_bind_tools so they are ready as soon as the integration activates.
4. Triggers (optional)
Triggers let workflows and todos start from the app’s events. EachTriggerConfig names a Composio trigger slug. Its handler lives in apps/api/app/services/triggers/handlers/ and is registered in apps/api/app/services/triggers/__init__.py. Instance toolkits have no triggers, because there is no generic handler.
5. Test it
apps/api/tests/unit/config/test_composio_integration_config.pychecks every Composio entry’s invariants. Run it withmise test:one tests/unit/config/test_composio_integration_config.py.- Boot the stack with
mise dev --agent, connect the integration from the integrations page and ask GAIA to use it. The driving-gaia cookbook covers driving chat and checking the result in Mongo. - On a self-hosted instance, open Settings → Integrations setup, click Set up automatically next to it, then Set up in the catalog that opens. That creates the auth config in the instance’s own Composio project.

