Skip to main content
Charm dispatches execution lifecycle events (run start/end, tool calls, LLM tokens, errors) to a TelemetryManager inside the agent container. By default, events stream to stdout for the cloud runner to forward as SSE. You can add custom exporters to forward the same events to Datadog, LangSmith, Sentry, etc.
Telemetry plugins run inside the agent container, not in the store or cloud-runner API process.
[!TIP] Want to build a new exporter? Use the charm-telemetry-template to bootstrap your project. It includes the correct entry points and BaseTelemetryExporter setup.

1. Implement BaseTelemetryExporter

Subclass charm.core.telemetry.BaseTelemetryExporter. All abstract hook methods must be implemented (use pass for hooks you do not need):
import os
from typing import Any, Dict
from charm.core.telemetry import BaseTelemetryExporter

class DataDogExporter(BaseTelemetryExporter):
    def __init__(self) -> None:
        self.api_key = os.getenv("DATADOG_API_KEY", "")

    def on_run_start(self, run_id: str, inputs: Dict[str, Any]) -> None:
        pass

    def on_run_end(self, run_id: str, outputs: Dict[str, Any]) -> None:
        pass

    def on_error(self, run_id: str, error: Exception) -> None:
        pass

    def on_tool_start(self, tool_name: str, input_str: str) -> None:
        pass

    def on_tool_end(self, tool_name: str, output: str) -> None:
        pass

    def on_tool_error(self, tool_name: str, error: BaseException) -> None:
        pass

    def on_llm_new_token(self, token: str) -> None:
        pass

    def on_agent_action(self, tool: str, tool_input: str) -> None:
        pass

2. Register via entry points

[project.entry-points."charm.telemetry"]
datadog = "charm_telemetry_datadog.exporter:DataDogExporter"

3. Opt in from charm.yaml

Exporters are opt-in — list the entry point names you want loaded:
runtime:
  adapter:
    type: custom
    entry_point: src.main:agent
  telemetry:
    - datadog
The default CharmEmitterExporter always runs; listed plugins are added to the dispatch list.

4. Zero-Config Cloud Deployment

Unlike heavy adapters, Telemetry plugins are typically lightweight (e.g. requests, API clients). This means the Charm Cloud Runner can install them dynamically at boot time without timing out. You do NOT need a custom_image to use a Telemetry Exporter!
  1. Add the package to your agent’s requirements.txt:
charm-telemetry-datadog
  1. Enable it in charm.yaml:
runtime:
  telemetry:
    - datadog
  1. Inject secrets via environment variables (e.g. DATADOG_API_KEY) through the Store agent settings or runner env resolution — never hard-code keys in charm.yaml.
When you deploy, the runner will execute uv pip install -r requirements.txt in a fraction of a second, and your agent will start sending telemetry immediately.

5. Share with the Community

Once your telemetry exporter is working and published to PyPI, you can list it in the official Charm Store! Submit a Pull Request to the charm-community-plugin repository to add your package to telemetry/registry.json. Your integration will immediately appear on the Plugins page for other developers to discover.