Skip to content

feat(ag2): add first-class instrumentation - #3379

Merged
mikeldking merged 13 commits into
Arize-ai:mainfrom
lxingy3:feat/ag2-instrumentation
Aug 7, 2026
Merged

mikeldking merged 13 commits into
Arize-ai:mainfrom
lxingy3:feat/ag2-instrumentation

Conversation

@lxingy3

@lxingy3 lxingy3 commented Jul 12, 2026 •

Copy link
Copy Markdown
Contributor

Closes #1332.

Summary

  • add the first-class openinference-instrumentation-ag2 package and openinference.instrumentation.ag2 API
  • trace AG2 chat runs, agent replies, and function execution across synchronous and asynchronous paths
  • keep openinference-instrumentation-autogen as a compatibility package for the legacy autogen distribution
  • register the AG2 package with tox, release-please, Dependabot, and the repository package index

Instrumentation behavior

Chat runs emit CHAIN spans, individual replies emit AGENT spans, and function execution emits TOOL spans. The wrappers use BaseInstrumentor and OITracer, honor OpenTelemetry suppression, carry OpenInference context attributes, apply TraceConfig masking, report tool failures, and restore all patched methods on uninstrumentation.

Tool spans include normalized input parameter definitions; return annotations are excluded from tool.parameters. Provider SDK instrumentors remain responsible for LLM spans.

Compatibility

The deprecated AutogenInstrumentor retains its autogen>=0.5.0 dependency check and delegates patching to the same AG2Instrumentor singleton. This keeps existing installations working without double-patching when both entry points are present.

The AG2 package targets the pre-1.0 autogen API. AG2 1.0 uses an async middleware and event model and should be supported separately through that native interface. openinference-instrumentation-autogen-agentchat is unchanged.

Validation

  • tox run -e py314-ci-ag2
  • tox run -e py314-ci-ag2-latest
  • tox run -e py314-ci-autogen
  • tox run -e py314-ci-autogen-latest

All four environments pass Ruff, strict mypy, wheel installation, and pytest. The compatibility environments exercise the real autogen==0.5.0 distribution and its latest release without ag2 installed.

A local Phoenix 18.0.0 trace confirmed the CHAIN -> AGENT -> TOOL hierarchy, successful tool input/output capture, and the normalized {"a":"int","b":"int"} parameter definition.

Trace output

Phoenix 18.0.0 showing the CHAIN -> AGENT -> TOOL hierarchy and normalized tool parameter metadata:
openinference-pr-3379-phoenix-trace

@github-actions

github-actions Bot commented Jul 12, 2026 •

Copy link
Copy Markdown
Contributor

CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅

@lxingy3

lxingy3 commented Jul 12, 2026

Copy link
Copy Markdown
Contributor Author

I have read the CLA Document and I hereby sign the CLA

@lxingy3
lxingy3 marked this pull request as ready for review July 12, 2026 04:34
@lxingy3
lxingy3 requested review from a team as code owners July 12, 2026 04:34
@dosubot dosubot Bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Jul 12, 2026
github-actions Bot added a commit that referenced this pull request Jul 12, 2026
@lxingy3

lxingy3 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor Author

Synced this branch with current main (fd88ec8) and resolved the two configuration conflicts while preserving the AG2 package metadata and the legacy autogen compatibility dependency.

Local validation passes on Python 3.14:

  • py314-ci-ag2
  • py314-ci-ag2-latest
  • py314-ci-autogen
  • py314-ci-autogen-latest

The PR is mergeable again and ready for review.

- Restore the legacy SpanAttributes class on the autogen compat package
- Track instrumentation ownership in the facade so uninstrument() no longer
  tears down instrumentation installed independently via AG2Instrumentor
- Accept the legacy autogen/pyautogen distribution names in the dependency
  check so instrument() is not a silent no-op, and drop the facade's
  skip_dep_check bypass and dead instrumentation_dependencies
- Bound the autogen instruments extra to <1.0.0
- Normalize string func_call arguments before delegating to execute_function
- Record the chat span's output.value as the final message content and emit
  the root chat span as AGENT kind, matching the legacy instrumentor
- Disable use_span's own exception recording to avoid duplicate exception
  events on error spans
- Replace the custom _json_value serializer with the shared
  get_input_attributes/get_output_attributes helpers
Adds an examples directory matching the convention used by the other Python
instrumentors. Two examples run without an LLM API key so the instrumentation
can be verified against a local Phoenix instance immediately; the other two
cover LLM-driven tool calling and the async agent paths.
@dosubot dosubot Bot added size:XXL This PR changes 1000+ lines, ignoring generated files. and removed size:XL This PR changes 500-999 lines, ignoring generated files. labels Aug 7, 2026
Replaces the single tool-calling example with examples that follow the AG2
user guide: the quickstart agent driven by run(), LLM-driven tool calling,
an AutoPattern group chat, sequential chats with carryover, and structured
outputs. Each example sets its own Phoenix project through the
openinference.project.name resource attribute so traces stay separated.
Calling execute_function directly left the TOOL span as its own trace root,
which is not how tool calls appear in a real AG2 run. Executing the tool from
a registered reply nests the TOOL span under generate_reply, matching the
shape an LLM-driven tool call produces.
Adds module, class, and function docstrings covering what each wrapper traces
and why the non-obvious paths exist: the alias-aware dependency check, the
suppressed exception recording on use_span, and the string func_call
normalization.

Also drops the dependabot entry for the new package from this PR.
Restores the weekly pip update entry for the AG2 instrumentation package,
matching the cooldown and ignore rules used by the other Python packages.
- Normalize a string func_call before the suppression check, so suppressing
  tracing no longer changes the call and crashes execute_function
- Bind the caller's context to async wrapper coroutines: AG2 runs async tools
  from its sync reply path on a fresh thread, which orphaned the tool span and
  dropped its context attributes
- Resolve tool parameter types with get_type_hints, which strips Annotated and
  resolves the string annotations PEP 563 produces; both cases previously
  reported useless type names
- Leave output.value unset when a reply is None and fall back to the chat
  summary when the history is empty, instead of recording "None" or a repr
- Build tool parameters defensively so unreadable annotations cannot break the
  wrapped call
- Uninstrument the autogen facade whenever instrument() was called on it, so a
  matched pair still restores the patched methods when the AG2 entry point was
  loaded first
- Run the autogen tox environments for ag2-only diffs, since the facade imports
  the ag2 package at module import time
Adds the standard collector blurb naming Phoenix, Arize AX, and Langfuse, the
phoenix serve quickstart walkthrough, and the shared More Info links, keeping
the AG2 version support note, span kind table, and examples pointer.
@mikeldking
mikeldking enabled auto-merge (squash) August 7, 2026 13:52

@mikeldking mikeldking left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Appreciate the contribution!

@mikeldking
mikeldking merged commit 2b2d78f into Arize-ai:main Aug 7, 2026
28 checks passed
@mikeldking mikeldking mentioned this pull request Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[instrumentation] AG2

2 participants