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 |
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.managepermission.
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.mdas an entry point, or place Skills beneath a sharedaai-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.
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-cliSkills 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.mdRuntime 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.
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 |