> ## Documentation Index
> Fetch the complete documentation index at: https://docs.charmos.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Telemetry Exporters

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](https://github.com/CharmAIOS/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):

```python theme={"theme":{"light":"min-light","dark":"min-dark"}}
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

```toml theme={"theme":{"light":"min-light","dark":"min-dark"}}
[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:

```yaml theme={"theme":{"light":"min-light","dark":"min-dark"}}
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`:

```txt theme={"theme":{"light":"min-light","dark":"min-dark"}}
charm-telemetry-datadog
```

2. Enable it in `charm.yaml`:

```yaml theme={"theme":{"light":"min-light","dark":"min-dark"}}
runtime:
  telemetry:
    - datadog
```

3. **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](https://github.com/CharmAIOS/charm-community-plugin) repository to add your package to `telemetry/registry.json`. Your integration will immediately appear on the [Plugins](/plugins) page for other developers to discover.

## Related

* [Extensibility Overview](/guides/extensibility)
* [Observability](/platform/observability)
* [Custom Runtimes](/guides/custom-runtimes)
