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

# Observability

> Monitor and debug agent runs with OpenTelemetry tracing, token usage, and integration with AgentScope Studio or third-party platforms

AgentScope provides **observability** so you can monitor and debug the execution of your agent applications. Built on **OpenTelemetry**, it gives you tracing across LLM calls, tool invocations, agent replies, and formatters—with optional visualization in **AgentScope Studio** or export to third-party platforms.

<CardGroup cols={3}>
  <Card title="Tracing" icon="route">
    Built-in spans for LLM, tool, agent reply, and formatter with error and exception tracking.
  </Card>

  <Card title="AgentScope Studio" icon="display">
    Native visualization of traces and token usage when you connect your run to Studio.
  </Card>

  <Card title="Third-Party Export" icon="plug">
    Send traces to OTLP-compatible backends (e.g. Arize-Phoenix, Langfuse, Alibaba Cloud).
  </Card>
</CardGroup>

<Info>
  Connecting to AgentScope Studio or a third-party tracing endpoint is done at application startup via [agentscope.init](/api-reference/introduction). See [Settings](/essentials/settings) for other init options.
</Info>

***

## Overview

Observability in AgentScope is implemented with **OpenTelemetry**. The framework instruments:

* **LLM calls** — each model `__call__` (chat, streaming, tools)
* **Agent replies** — each agent `reply` (reasoning and acting)
* **Formatters** — message formatting before sending to the model
* **Tools** — toolkit `call_tool_function` invocations
* **Embeddings** — embedding model calls

Spans are emitted in OTLP format, so you can view them in AgentScope Studio or any OTLP-compatible backend. Your own OpenTelemetry instrumentation is compatible with AgentScope and will appear in the same trace context.

***

## Setting Up Tracing

### AgentScope Studio

When you run agents with **AgentScope Studio**, you get built-in **trace visualization** and **token usage** views. Configure the connection at the start of your application:

```python theme={null}
import agentscope

# Connect to your Studio instance; traces and token usage will appear in the Studio UI
agentscope.init(studio_url="http://localhost:port")
```

Once connected, Studio receives traces and run metadata so you can inspect spans, latency, and token consumption per run.

### Third-Party Platforms

To send traces to an **OpenTelemetry-compatible backend** (or your own OTLP collector), set `tracing_url` in `agentscope.init`. The URL must be the OTLP trace endpoint.

```python theme={null}
import agentscope

# Generic OTLP endpoint
agentscope.init(tracing_url="https://your-backend:4318/v1/traces")
```

If you pass both `studio_url` and `tracing_url`, traces are sent to `tracing_url`; if you pass only `studio_url`, traces are sent to Studio’s tracing endpoint.

<Note>
  Use either **Studio** (`studio_url`) or a **third-party** (`tracing_url`) for trace export, or both when you want Studio for UI and a separate backend for storage/analysis.
</Note>

***

## Connecting to Third-Party Backends

The following examples show how to point AgentScope at popular OTLP-compatible backends.

### Alibaba Cloud CloudMonitor

[Alibaba Cloud CloudMonitor](https://www.alibabacloud.com/help/en/cms/cloudmonitor-2.0/user-guide/model-application) supports OTLP. Use the public endpoint for your region from the ARMS console (**Access Center** > **OpenTelemetry**). You can set the service name with the `OTEL_SERVICE_NAME` environment variable.

```python theme={null}
import agentscope

agentscope.init(tracing_url="https://tracing-cn-hangzhou.arms.aliyuncs.com/adapt_xxx/api/otlp/traces")
```

### Arize Phoenix

[Arize Phoenix](https://github.com/Arize-ai/phoenix) accepts OTLP. Set `PHOENIX_API_KEY` in your environment and pass Phoenix’s trace endpoint:

```python theme={null}
import os
import agentscope

os.environ["OTEL_EXPORTER_OTLP_HEADERS"] = f"api_key={os.environ.get('PHOENIX_API_KEY')}"
agentscope.init(tracing_url="https://app.phoenix.arize.com/v1/traces")
```

### Langfuse

[Langfuse](https://langfuse.com/) supports OTLP. Configure `LANGFUSE_PUBLIC_KEY` and `LANGFUSE_SECRET_KEY`, then set the `Authorization=Basic ...` header for the OTLP exporter:

```python theme={null}
import os
import base64
import agentscope

LANGFUSE_PUBLIC_KEY = os.environ["LANGFUSE_PUBLIC_KEY"]
LANGFUSE_SECRET_KEY = os.environ["LANGFUSE_SECRET_KEY"]
auth_string = f"{LANGFUSE_PUBLIC_KEY}:{LANGFUSE_SECRET_KEY}"
auth_b64 = base64.b64encode(auth_string.encode("utf-8")).decode("ascii")
os.environ["OTEL_EXPORTER_OTLP_HEADERS"] = f"Authorization=Basic {auth_b64}"

# EU region
agentscope.init(tracing_url="https://cloud.langfuse.com/api/public/otel/v1/traces")
# US region: https://us.cloud.langfuse.com/api/public/otel/v1/traces
```

<Tip>
  For more on run identity and logging, see the `project`, `name`, `run_id`, and `logging_path` arguments of [agentscope.init](/api-reference/introduction). `run_id` is especially useful in Studio to distinguish different runs.
</Tip>

***

## Customizing Tracing

AgentScope’s tracing is implemented with OpenTelemetry; custom spans you create with the OpenTelemetry SDK will appear in the same trace tree. In addition, the following **decorators** are available to trace framework components:

| Decorator            | Target                       | Description                                           |
| -------------------- | ---------------------------- | ----------------------------------------------------- |
| `@trace_llm`         | `ChatModelBase.__call__`     | Traces LLM invocations (chat, stream, tools).         |
| `@trace_reply`       | `AgentBase.reply`            | Traces agent reply (reasoning and acting).            |
| `@trace_format`      | `FormatterBase.format`       | Traces message formatting.                            |
| `@trace_toolkit`     | `Toolkit.call_tool_function` | Traces tool calls.                                    |
| `@trace_embedding`   | Embedding model `__call__`   | Traces embedding API calls.                           |
| `@trace(name="...")` | Any function                 | General-purpose tracer for sync/async and generators. |

These decorators are already applied to the built-in model, agent, formatter, and toolkit classes. You only need to use them when **defining your own** model, agent, or formatter classes.

### Tracing a Custom Chat Model

Your custom model must inherit from `ChatModelBase`. Apply `@trace_llm` to `__call__` so its calls appear in traces:

```python theme={null}
from agentscope.model import ChatModelBase
from agentscope.tracing import trace_llm

class MyChatModel(ChatModelBase):
    @trace_llm
    async def __call__(self, messages, **kwargs):
        # Your implementation
        ...
```

### Tracing a Custom Agent

Your custom agent must inherit from `AgentBase`. Apply `@trace_reply` to `reply`:

```python theme={null}
from agentscope.agent import AgentBase
from agentscope.tracing import trace_reply

class MyAgent(AgentBase):
    @trace_reply
    async def reply(self, *args, **kwargs):
        # Your implementation
        ...
```

### Tracing a Custom Formatter

Your custom formatter must inherit from `FormatterBase`. Apply `@trace_format` to `format`:

```python theme={null}
from agentscope.formatter import FormatterBase
from agentscope.tracing import trace_format

class MyFormatter(FormatterBase):
    @trace_format
    async def format(self, *args, **kwargs):
        # Your implementation
        ...
```

### General-Purpose Tracing

Use `@trace(name="...")` on any function—sync or async, including generators—to add a span with the given name:

```python theme={null}
from agentscope.tracing import trace

@trace(name="my_step")
async def my_async_step(data: dict) -> dict:
    return {"processed": data}

@trace(name="my_sync_fn")
def my_sync_fn(x: int) -> int:
    return x + 1
```

***

## Token Usage

Token usage is tracked by the model layer and is included in trace metadata where supported. When you connect to **AgentScope Studio**, token consumption is visualized in the Studio UI so you can monitor cost and usage per run. For third-party backends, token-related attributes are exported with the LLM spans according to the OpenTelemetry semantic conventions used by AgentScope.

For programmatic access to usage after a model call, use the `usage` field on the [ChatResponse](/versions/1.0.21/en/building-blocks/models) returned by the model.

***

## Summary

* Call **agentscope.init(studio\_url=...)** for Studio tracing and token visualization, or **agentscope.init(tracing\_url=...)** for an OTLP backend (or both).
* Use **AgentScope Studio** for built-in trace and token usage views.
* Use **tracing\_url** to send traces to Arize-Phoenix, Langfuse, Alibaba Cloud CloudMonitor, or any OTLP endpoint.
* Use **@trace\_llm**, **@trace\_reply**, **@trace\_format**, **@trace\_toolkit**, **@trace\_embedding**, and **@trace** when implementing custom models, agents, or formatters so they appear in the same trace tree.

For evaluation of agent behavior and benchmarks, see [Evaluation](/versions/1.0.21/en/observe-and-evaluate/evaluation).
