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

# AG2

> Trace AG2 0.14 agent chats and tool execution with OpenInference in Arize AX.

[AG2](https://github.com/ag2ai/ag2) is an agent framework built on the
`autogen` API. The
[`AG2Instrumentor`](https://github.com/Arize-ai/openinference/tree/main/python/instrumentation/openinference-instrumentation-ag2)
captures ConversableAgent chats, replies, and tool execution as OpenInference
AGENT and TOOL spans in Arize AX.

AG2 is a fork of the original 0.2-style AutoGen project. This integration is
for AG2's `autogen` module, not AG2 v1 or Microsoft's separate
`autogen-agentchat` package. See the [Microsoft AutoGen AgentChat guide](/docs/ax/integrations/python-agent-frameworks/autogen/autogen-agentchat-tracing)
for the latter.

## Prerequisites

* Python 3.10+
* An Arize AX account ([sign up](https://arize.com/sign-up/))

This guide uses AG2's offline multi-agent and tool-call pattern, so it does not
need an LLM provider key.

## Launch Arize AX

1. Sign in to your [Arize AX account](https://app.arize.com/).
2. From **Space Settings**, copy your **Space ID** and **API Key**. You will set them as `ARIZE_SPACE_ID` and `ARIZE_API_KEY` below.

## Install

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
pip install arize-otel openinference-instrumentation-ag2 "ag2<1.0"
```

## Configure credentials

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
export ARIZE_SPACE_ID="<your-space-id>"
export ARIZE_API_KEY="<your-api-key>"
export ARIZE_PROJECT_NAME="ag2-tracing-example"
```

## Setup tracing

```python theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
# instrumentation.py
import os

from arize.otel import register
from openinference.instrumentation.ag2 import AG2Instrumentor

tracer_provider = register(
    space_id=os.environ["ARIZE_SPACE_ID"],
    api_key=os.environ["ARIZE_API_KEY"],
    project_name=os.environ["ARIZE_PROJECT_NAME"],
)

AG2Instrumentor().instrument(tracer_provider=tracer_provider)
print("Arize AX tracing initialized for AG2.")
```

AG2 instrumentation supports the AG2 0.14.x `autogen` API. AG2 v1 uses a
different middleware API and is not yet supported.

## Spans and context captured

AG2 creates an AGENT span for each chat and agent reply. Reply spans nest under
their chat span, and a function call made while producing a reply becomes a
child TOOL span:

| AG2 operation                                                                 | Span name                | Span kind |
| ----------------------------------------------------------------------------- | ------------------------ | --------- |
| `initiate_chat` / `a_initiate_chat` (also used by `run` and `initiate_chats`) | `<agent>.initiate_chat`  | `AGENT`   |
| `generate_reply` / `a_generate_reply`                                         | `<agent>.generate_reply` | `AGENT`   |
| `execute_function` / `a_execute_function`                                     | `<tool>`                 | `TOOL`    |

Tool spans use the registered function name (for example, `get_weather`) and
record `tool.name`, `tool_call.id`, `tool_call.function.arguments`, resolved
`tool.parameters`, and the result. Agent spans record the input and output
messages and the agent name.

The instrumentor preserves the active OpenTelemetry context, so an AG2 chat
started inside one of your application's spans remains in that trace. Context
also flows through nested replies and tool execution. Use
[`using_attributes`](/docs/ax/instrument/set-up-sessions) to
propagate a session ID, user ID, metadata, and tags to all AG2 spans within a
context block. Pair it with the
[`OpenAIInstrumentor`](https://github.com/Arize-ai/openinference/tree/main/python/instrumentation/openinference-instrumentation-openai)
when an AG2 agent uses OpenAI: this adds LLM child spans below the AGENT spans.

The standard OpenInference privacy controls apply. Use
[`suppress_tracing`](/docs/ax/concepts/otel-openinference/context-managers)
around calls you do not want to trace. Set
`OPENINFERENCE_HIDE_INPUTS=true`, `OPENINFERENCE_HIDE_OUTPUTS=true`,
`OPENINFERENCE_HIDE_INPUT_MESSAGES=true`, or
`OPENINFERENCE_HIDE_OUTPUT_MESSAGES=true` before starting your process to mask
the corresponding captured values. For programmatic masking or image
truncation, configure [`TraceConfig`](/docs/ax/instrument/mask-and-redact-data),
which takes precedence over environment variables.

## Run AG2

```python theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
# example.py
import json
from typing import Any

from instrumentation import tracer_provider
from autogen import ConversableAgent


def get_weather(city: str) -> str:
    return f"It is 72F and sunny in {city}."


def reply_with_weather(
    agent: ConversableAgent,
    messages: list[dict[str, Any]] | None = None,
    sender: Any = None,
    config: Any = None,
) -> tuple[bool, str]:
    _, result = agent.execute_function(
        {"name": "get_weather", "arguments": json.dumps({"city": "Portland"})},
        call_id="call-1",
    )
    return True, str(result["content"])


weather_agent = ConversableAgent(
    "weather_agent",
    llm_config=False,
    human_input_mode="NEVER",
)
weather_agent.register_function({"get_weather": get_weather})
weather_agent.register_reply(
    [ConversableAgent, None],
    reply_with_weather,
    position=0,
)

user_proxy = ConversableAgent(
    "user_proxy",
    llm_config=False,
    human_input_mode="NEVER",
)
chat = user_proxy.initiate_chat(
    weather_agent,
    message="What is the weather in Portland?",
    max_turns=1,
    silent=True,
)
print("weather_agent:", chat.chat_history[-1]["content"])
```

### Expected output

```text wrap theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
Arize AX tracing initialized for AG2.
weather_agent: It is 72F and sunny in Portland.
```

## More AG2 patterns

The quickstart above is deliberately offline. The following upstream-inspired
patterns require `OPENAI_API_KEY` and the optional packages shown below. Add
`openai` and `openinference-instrumentation-openai` to the install command, then
instrument OpenAI before AG2:

```python theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
from openinference.instrumentation.openai import OpenAIInstrumentor

OpenAIInstrumentor().instrument(tracer_provider=tracer_provider)
```

Use a real model available to your account in `config_list`.

### Group chat

```python theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
import os

from autogen import ConversableAgent, LLMConfig
from autogen.agentchat import initiate_group_chat
from autogen.agentchat.group.patterns import AutoPattern

llm_config = LLMConfig({"api_type": "openai", "model": "gpt-5.4-mini", "api_key": os.environ["OPENAI_API_KEY"]})
writer = ConversableAgent("writer", llm_config=llm_config)
reviewer = ConversableAgent("reviewer", llm_config=llm_config)
pattern = AutoPattern(initial_agent=writer, agents=[writer, reviewer], group_manager_args={"llm_config": llm_config})
result, _, _ = initiate_group_chat(pattern=pattern, messages="Write and review a one-sentence slogan.", max_rounds=3)
print(result.chat_history[-1]["content"])
```

### Sequential chats

```python theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
import os

from autogen import ConversableAgent, LLMConfig

llm_config = LLMConfig({"api_type": "openai", "model": "gpt-5.4-mini", "api_key": os.environ["OPENAI_API_KEY"]})
researcher = ConversableAgent("researcher", llm_config=llm_config)
editor = ConversableAgent("editor", llm_config=llm_config)
coordinator = ConversableAgent("coordinator", human_input_mode="NEVER")
coordinator.initiate_chats([
    {"recipient": researcher, "message": "List two benefits of tracing.", "max_turns": 1, "summary_method": "last_msg"},
    {"recipient": editor, "message": "Turn those benefits into one sentence.", "max_turns": 1, "summary_method": "last_msg"},
])
```

### Structured outputs

```python theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
from pydantic import BaseModel
import os

from autogen import ConversableAgent, LLMConfig

class Weather(BaseModel):
    city: str
    temperature_f: int

llm_config = LLMConfig(
    {"api_type": "openai", "model": "gpt-5.4-mini", "api_key": os.environ["OPENAI_API_KEY"]},
    response_format=Weather,
)
agent = ConversableAgent(
    "weather",
    llm_config=llm_config,
)
response = agent.run(message="Return Portland weather.", max_turns=1, user_input=False)
response.process()
print(Weather.model_validate_json(response.messages[-1]["content"]))
```

These patterns follow the [AG2 instrumentor examples](https://github.com/Arize-ai/openinference/tree/main/python/instrumentation/openinference-instrumentation-ag2/examples).

## Verify in Arize AX

1. Open your Arize AX space and select project **`ag2-tracing-example`**.
2. You should see a new trace within \~30 seconds with AGENT spans for the chat and reply, plus a TOOL span named `get_weather`.
3. If no traces appear, see [Troubleshooting](#troubleshooting).

### Check from the skill, CLI, or SDK

Confirm spans are actually reaching your Arize AX project. Use whichever fits your workflow — the skill and CLI work for any framework; the SDK check is shown for each language.

<Tabs>
  <Tab title="Arize skill (agent)">
    Install the [Arize Skills](https://github.com/Arize-ai/arize-skills) plugin and let your coding agent check for you:

    ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
    npx skills add Arize-ai/arize-skills
    ```

    Then prompt your agent:

    > Use the `arize-trace` skill to export and analyze recent traces from my project. Confirm spans are arriving, and summarize any errors or latency issues.
  </Tab>

  <Tab title="AX CLI">
    Export recent spans for your project — any rows mean traces are landing:

    ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
    ax spans export "$ARIZE_PROJECT_NAME" --space "$ARIZE_SPACE_ID" \
      --limit 5 --stdout | jq 'length'
    ```

    A non-zero count confirms spans reached Arize AX. Run `ax auth login` first if you have not authenticated. See the [`ax spans` reference](/docs/api-clients/cli/spans).
  </Tab>

  <Tab title="SDK">
    Query the project's spans and check that at least one came back.

    <CodeGroup>
      ```python Python theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
      import os
      from arize import ArizeClient

      client = ArizeClient(api_key=os.environ["ARIZE_API_KEY"])
      resp = client.spans.list(
          project=os.environ["ARIZE_PROJECT_NAME"],
          space=os.environ["ARIZE_SPACE_ID"],
          limit=5,
      )
      count = len(resp.spans)
      print(
          f"{count} span(s) found" if count else "No spans yet — recheck setup"
      )
      ```

      ```typescript TypeScript theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
      // Reads ARIZE_API_KEY from the environment.
      import { listSpans } from "@arizeai/ax-client";

      const { data: spans } = await listSpans({
        project: process.env.ARIZE_PROJECT_NAME!,
        space: process.env.ARIZE_SPACE_ID!,
        limit: 5,
      });
      const count = spans.length;
      console.log(
        count ? `${count} span(s) found` : "No spans yet — recheck setup",
      );
      ```

      ```go Go theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
      client, err := arize.NewClient(
          arize.Config{APIKey: os.Getenv("ARIZE_API_KEY")},
      )
      if err != nil {
          log.Fatal(err)
      }
      resp, err := client.Spans.List(ctx, spans.ListRequest{
          Project: os.Getenv("ARIZE_PROJECT_NAME"),
          Space:   os.Getenv("ARIZE_SPACE_ID"),
          Limit:   5,
      })
      if err != nil {
          log.Fatal(err)
      }
      fmt.Printf("%d span(s) found\n", len(resp.Spans))
      ```
    </CodeGroup>

    SDK span references: [Python](/docs/api-clients/python/version-8/client-resources/spans) · [TypeScript](/docs/api-clients/typescript/version-1/client-resources/spans) · [Go](/docs/api-clients/go/version-2/client-resources/spans).
  </Tab>
</Tabs>

## Troubleshooting

* **No traces in Arize AX.** Call `AG2Instrumentor().instrument(...)` before starting a chat.
* **Import or instrumentation error.** Install an AG2 0.14.x release; AG2 v1 is not supported by this instrumentor.
* **The example asks for an LLM key.** Keep both agents' `llm_config=False`; this offline example runs a local tool instead of calling a model.
* **LLM spans are missing.** Install and initialize `OpenAIInstrumentor` before AG2 when your agents use OpenAI.

## Resources

<CardGroup>
  <Card icon="terminal" href="https://github.com/Arize-ai/openinference/tree/main/python/instrumentation/openinference-instrumentation-ag2" title="OpenInference AG2 Instrumentor" horizontal />

  <Card icon="github" href="https://github.com/ag2ai/ag2" title="AG2 repository" horizontal />
</CardGroup>
