Skip to main content
Charm separates a small stable core from community-owned extensions. Not every extension works the same way — some are runtime Python plugins, some are store contributions, and some are manifest PRs. Use this page to pick the right path before you start building.

Extension paths at a glance

Two kinds of “custom” (important)

These names overlap — they are not the same thing: Scenario: you can use type: custom with custom_image (extra deps, no new adapter class).
Scenario: you can use type: ag2 with custom_image (new adapter plugin + image that installs it).
  1. Start from a normal agentcharm init my-agent --template python
  2. Add a pip package with your adapter/telemetry/memory classes and pyproject.toml entry points
  3. Point charm.yaml at your pluginruntime.adapter.type: your_plugin_name
  4. Add to requirements.txt (if lightweight like Telemetry or Memory) OR Build a custom_image (if heavy like Adapters)
  5. Set runtime.custom_image in charm.yaml (if you built a Docker image)
  6. charm validatecharm push → run on the Store
Note: The cloud runner will execute uv pip install -r requirements.txt at runtime. For lightweight plugins, this is all you need. For heavy plugins (like third-party adapters), you must bake them into a custom_image to avoid boot timeouts.

Built-in vs third-party

Cloud prerequisites

For any custom image on production:
  1. Push the image to a registry the runner can pull (Artifact Registry, GHCR, etc.)
  2. Grant the runner service account read access to that registry (if private)
  3. Declare runtime.custom_image in charm.yaml — the runner selects it over default adapter images
See Base Images and Custom Runtimes.

Next steps

For core contributors merging adapters into the official SDK, see Write a Custom Adapter (in-repo process).