Skip to main content
Use this guide when you are a plugin author integrating a new Python framework (AG2, AutoGen, an internal runtime, etc.) — not when you only need a plain Python function agent.
Using plain Python only? You probably want the built-in custom adapter from charm init --template python. See Custom Python Adapter. This guide is for registering a new adapter name via entry points.

How discovery works

Charm loads adapters from Python entry_points in the charm.adapters group. The name you register becomes a valid runtime.adapter.type in charm.yaml. Official adapters (langchain, crewai, openclaw, custom, …) use the same mechanism in the charmos package. Third-party packages add more names without forking core.

1. Get the Boilerplate

[!TIP] Fastest Path: You do not need to write this from scratch. Use the official charm-adapter-template repository on GitHub. Click Use this template, rename the folder, and jump straight to implementing your invoke method.
If you are doing it manually, start by scaffolding a plain project:
charm init my-ag2-agent --template python
cd my-ag2-agent
This scaffolds charm.yaml, src/main.py, and .charmignore. You will add a separate installable package (or a pyproject.toml in the same repo) for the adapter plugin.

2. Implement BaseAdapter

Your class must inherit from charm.adapters.base.BaseAdapter and implement invoke.
from typing import Any, Dict, List, Optional
from charm.adapters.base import BaseAdapter

class Ag2Adapter(BaseAdapter):
    def invoke(
        self, inputs: Dict[str, Any], callbacks: Optional[List[Any]] = None
    ) -> Dict[str, Any]:
        # self.agent is the object imported from runtime.adapter.entry_point
        result = self.agent.run(**inputs)
        return {
            "status": "success",
            "output": result,
        }
The loader constructs your adapter as AdapterClass(agent_instance=..., config=...) after importing the user’s entry point from charm.yaml. Return a dict with "status": "success" and "output" for standard Store rendering, or include structured keys like _charm_render_type (see Output Renderers).

3. Register via entry points

In your plugin package’s pyproject.toml:
[project]
name = "charm-adapter-ag2"
version = "0.1.0"
dependencies = ["charmos"]

[project.entry-points."charm.adapters"]
ag2 = "charm_adapter_ag2.adapter:Ag2Adapter"
Install locally while developing:
pip install -e ./path/to/charm-adapter-ag2
pip install -e ./path/to/my-ag2-agent   # if separate
Verify discovery:
python -c "from importlib.metadata import entry_points; print([e.name for e in entry_points(group='charm.adapters')])"
charm validate should accept runtime.adapter.type: ag2 after your package is installed.

4. Configure charm.yaml

version: "0.4.2"

persona:
  name: "My AG2 Agent"
  description: "Agent using a third-party adapter plugin"
  version: "0.1.0"

interface:
  input:
    type: object
    required: [message]
    properties:
      message: { type: string }
  output:
    type: string

runtime:
  adapter:
    type: ag2
    entry_point: src.main:my_agent
  lifecycle: serverless

5. Cloud execution requires a custom image

The cloud runner will automatically uv pip install your adapter if it is listed in the user’s requirements.txt. However, if your adapter depends on massive libraries (like PyTorch or large LLM frameworks), uv pip install might timeout during Cloud Run startup. For heavy adapters, you should provide a custom image:
  1. Build a Docker image based on charm-base or an official runner image
  2. RUN uv pip install charm-adapter-ag2 (or pip install) inside the Dockerfile
  3. Set runtime.custom_image to the pushed image URI
runtime:
  custom_image: "ghcr.io/your-org/my-ag2-runtime:prod"
  adapter:
    type: ag2
    entry_point: src.main:my_agent

6. Submit to the Charm Store

To make your adapter discoverable by the global Charm community:
  1. Fork the charm-community-plugin repository.
  2. Edit adapters/registry.json to add your package name (charm-adapter-ag2).
  3. Submit a Pull Request.
Once merged, your adapter will instantly appear in the Charm Store Plugins Gallery, allowing users to one-click copy the install command. See Custom Runtimes for registry and IAM notes.

Local testing

# Validates adapter type (plugin must be installed in local env)
charm validate .

# Runs agent logic locally (uses local env, not necessarily your custom image)
charm run . --input "hello"

# Simulates cloud container (uses custom_image from charm.yaml)
charm run . --docker --input "hello"