---
title: Add an integration
canonical: "https://agentbarn.dev/guides/develop/add-integration"
pubDate: "2026-08-29T00:00:00.000Z"
updatedDate: "2026-09-13T13:41:42.000Z"
author: Agent Barn
description: "Learn how to add a tool Integration with credential validation, encrypted persistence, runtime materialization, provider metadata, isolated bundled Skills, web app configuration, and focused tests."
tags: [Develop and extend, How-to, Integration developers and maintainers, integration, provider, credentials, Agent Secrets, aai-cli, bundled Skills, Skill Version, OAuth, runtime, Skills, encryption, validation]
categories: [Guides, Develop and extend]
---

Add an external tool Integration by defining secure credentials, runtime materialization, a bundled Skill where applicable, validation, and user-facing configuration, without confusing tools with Communication transport.

## Classify the provider boundary

| External tool Integration | Communication Platform |
| --- | --- |
| Gives an Agent tools for an external service | Carries inbound and outbound messages |
| Uses an Agent Secret or eligible Shared Credential | Uses a Communication Connection and Platform Plugin |
| May be materialized into Runtime tooling | Owns provider ingress, durable Delivery, and Conversation Messages |
| Usually uses a CLI profile, OAuth, API token, or Runtime tool | Uses independent provider credentials, settings, and admission policy |

**Slack has two separate contracts**

Slack message delivery and Slack tool access are separate contracts. A Slack Communication Connection owns credentials used by the shipped Slack Platform Plugin. A Slack Agent Secret independently provides `aai-cli` Slack tool access. Connection credentials never become Agent Secrets, Shared Credentials, or Runtime Integration credentials.

## Define the credential contract

Update `SecretProvider`, a `SecretContent` subclass, `PROVIDER_CONTENT_MODELS`, and `PROVIDER_DISPLAY_NAMES`. Provider IDs are stable lowercase persisted identifiers, content models reject unknown fields, and payloads are validated before encryption and after decryption.

-   Read responses, Domain Events, logs, validation errors, and exceptions never contain credential content.
-   An Agent holds at most one credential for a provider, and uses either an Agent Secret or Shared Credential, not both.
-   Stored-schema changes preserve compatibility with existing encrypted payloads.
-   Credential creation, replacement, and retirement require the effective `agent.secret.manage` permission.

## Add an isolated bundled Skill

For an `aai-cli`\-backed Integration, add a checked-in bundle:

```
api/domains/agents/aai_cli_skills/bundled/skills/
└── aai-acme/
    ├── SKILL.md
    └── references/
        └── command-reference.md
```

-   Use the `aai-<integration>` directory slug.
-   Every bundled Skill has exactly one root `SKILL.md`; supporting Markdown stays beneath that isolated root and uses relative paths.
-   Do not create Python modules containing Markdown strings, use `acme_skill.md` as an entry point, or place Skills beneath a shared `aai-cli/` Runtime directory.

```
---
name: aai-acme
description: Use aai-cli to work with Acme resources through the configured Agent credential.
---

# aai-cli Acme

Use this skill when working with Acme through `aai-cli acme`.

Credentials are configured by Agent Barn. Do not ask the user to provide or paste credentials.

Confirm the active profile or pass the configured `--profile` value before running a command.

Successful output is JSON on stdout. Errors are structured JSON on stderr.

See [the command reference](references/command-reference.md) for supported resources, commands, response shapes, and error behavior.
```

This is structural. Document only commands confirmed against the pinned `aai-cli` implementation, never commands inferred from the provider REST API.

### Document the real CLI contract

`references/command-reference.md` documents the canonical profile name, authentication fields, resource and command groups, flags, pagination, response shapes, downloads, structured errors, exit codes, read versus mutation behavior, and provider-specific limitations.

```
aai-cli --profile acme-work acme <resource> <command>
```

## Register and seed bundled Skill metadata

Bundled metadata is assembled in `api/domains/agents/aai_cli_skills/__init__.py`.

```
_DISPLAY_NAMES = {
    # Existing entries...
    "aai-acme": "Acme",
}

_COMMANDS = {
    # Existing entries...
    "aai-acme": "acme",
}

_REQUIRED_PROVIDERS = {
    # Existing entries...
    "aai-acme": [SecretProvider.ACME],
}
```

`_DISPLAY_NAMES` supplies the user-facing Platform Skill name, `_COMMANDS` records the `aai-cli` command group for Runtime policy, and `_REQUIRED_PROVIDERS` declares required Agent Secret providers. The directory name remains the immutable Skill slug and Runtime root. Do not add an `ACME_SKILLS` constant or embed Skill files in Python.

**Bootstrap-only seeding**

`seed_aai_cli_skills()` treats checked-in bundles as bootstrap data. It creates and publishes v1 only when the Platform Skill slug does not exist. Once a lineage exists, its database-backed drafts, files, metadata, and published versions are canonical; startup does not overwrite or republish them.

New installations receive bundled Platform Skills at startup. Existing installations require the normal Platform Skill draft-and-publish workflow or an explicit migration for later content changes. Built-in `aai-cli` lineages remain protected from deletion and have no Organization or Agent owner.

## Declare provider requirements and materialize safely

`required_providers` is declarative Integration metadata. A Skill grants neither tools, permissions, nor credentials. An assigned Skill is valid only when required Agent Secret providers are configured.

-   Eligible built-in `aai-cli` Skills with non-empty provider requirements can auto-mount when all required providers are configured.
-   A built-in Skill with no provider requirements is never auto-mounted merely because its list is empty.
-   Credential-free Skills, including local-file Skills, must be assigned explicitly.
-   A checked-in bundle can be explicitly assignable before Agent Barn models an automatic credential lifecycle for it.

```
Hermes:
  /workspace/skills/aai-acme/SKILL.md

OpenClaw:
  /home/node/.openclaw/workspace/skills/aai-acme/SKILL.md

Tools pointer:
  ./skills/aai-acme/SKILL.md
```

Runtime materialization loads database-backed files, mounts them under the immutable Skill root, includes the exact selected or assigned Skill Version in its manifest, detects path collisions instead of overwriting, and keeps Integration bundles isolated.

For an `aai-cli` provider, update the applicable surfaces in `api/domains/agents/aai_cli_artifacts.py`: secret-store names, canonical profile slug, `config.toml`, temporary setup environment, configured-Integration context, policy text, and startup inputs. Continue treating Google Workspace through `gog` and Runtime-native capabilities such as Firecrawl as distinct materialization shapes.

**Security**

Only Kubernetes Secrets hold sensitive values. Skill files, ConfigMaps, `TOOLS.md`, `AGENTS.md`, committed profiles, and documentation remain secret-free.

## Validate credentials and opt into sharing deliberately

Provider validators live under `api/infrastructure/integration_validators/` and register in its `__init__.py`. A validator uses the smallest safe read-only provider request, can return safe identity or missing-scope information, and never persists provider responses or credential content. Providers without one remain schema-validated.

Shared Credentials are opt-in. Add only appropriate manual-entry providers to `SHARED_CREDENTIAL_ALLOWED_PROVIDERS`; OAuth credentials are not automatically shareable. Shared reads never include content, deletion remains blocked while an Agent references the credential, and Connection credentials are never eligible Shared Credentials.

## Update generic UI and preserve stored data

The provider catalogue lives in `ui/src/features/agents/integrations.ts`. Its provider ID must exactly equal the backend `SecretProvider`; camelCase field keys are converted to snake\_case content keys by the shared API client.

Use the reusable `text`, `secret`, `repo-list`, `radio`, and `checkbox-list` fields. `authMethod: "google_oauth"` is coupled to Google Workspace OAuth and must not be reused without a complete typed OAuth flow.

When evolving encrypted schemas, prefer optional defaults, compatibility validators, and staged transitions. Never rename or remove required fields, change a provider ID, or require new secrets for existing records without a migration plan.

## Source map

| Concern | Source |
| --- | --- |
| Provider enum and credential content | `api/domains/agents/models.py` |
| Agent Secret persistence and runtime orchestration | `api/domains/agents/service.py` |
| Agent Secret queries | `api/domains/agents/repository.py` |
| aai-cli runtime artifacts | `api/domains/agents/aai_cli_artifacts.py` |
| Bundled aai-cli Skill files | `api/domains/agents/aai_cli_skills/bundled/skills/` |
| Bundled Skill metadata and manifest behavior | `api/domains/agents/aai_cli_skills/__init__.py` |
| Bootstrap-only Platform Skill seeding | `api/domains/skills/skill_seeder.py` |
| Provider validator registry | `api/infrastructure/integration_validators/__init__.py` |
| Provider validators | `api/infrastructure/integration_validators/` |
| Shared Credential eligibility | `api/domains/shared_credentials/models.py` |
| Google Workspace runtime artifacts | `api/domains/agents/gog_artifacts.py` |
| UI Integration catalogue | `ui/src/features/agents/integrations.ts` |

## Related guides

-   [Work with Skills](/guides/templates-and-skills/skills) and [manage Skill Versions](/guides/templates-and-skills/skill-versions)
-   [Manage Agent credentials](/guides/integrations/credentials) and [Shared Credentials](/guides/integrations/shared-credentials)
-   [Communication Connections](/guides/agents/communication-connections) and [Add a communication platform](/guides/develop/add-platform)
