Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
a6a0479
feat(galileo-a2a): rebrand to SPLUNK_AO_* env vars and SplunkAOSpanPr…
adityamehra Jun 16, 2026
6afc9bd
fix(galileo-a2a): rename package to splunk-ao-a2a and reset to v0.1.0
adityamehra Jun 16, 2026
6d0aa1d
Merge branch 'main' into fix/splunk-ao-a2a-pyproject
adityamehra Jun 17, 2026
79f1996
refactor(galileo-a2a): rename dir to splunk-ao-a2a and module to splu…
adityamehra Jun 17, 2026
a739344
fix(splunk-ao-a2a): correct version ranges and stale docstring (PR #3…
adityamehra Jun 18, 2026
005daa2
Merge branch 'main' into fix/splunk-ao-a2a-pyproject
adityamehra Jun 18, 2026
d5bad72
ci: add GitHub Actions workflow to test splunk-ao-a2a
adityamehra Jun 23, 2026
5d175f9
fix(ci): use uv run pip list to avoid VIRTUAL_ENV override in show-ve…
adityamehra Jun 23, 2026
c2ad927
fix(ci): use pip show instead of pip list grep for installed versions…
adityamehra Jun 23, 2026
8c2a462
fix(ci): use uv tree --depth 1 for show-versions step to avoid VIRTUA…
adityamehra Jun 23, 2026
4512c71
fix(dev): pin PyPI as default uv index to bypass Splunk Artifactory i…
adityamehra Jun 23, 2026
e605a4d
fix(ci): fix show installed versions
adityamehra Jun 23, 2026
5485c6f
fix(ci): rename gh workflow
adityamehra Jun 23, 2026
3f98825
fix(dev): add uv.toml to splunk-ao-a2a to replace global Artifactory …
adityamehra Jun 23, 2026
4934d3a
Merge remote-tracking branch 'origin/main' into fix/splunk-ao-a2a-pyp…
adityamehra Jun 26, 2026
a8ceb17
fix(splunk-ao-a2a): replace SPLUNK_AO_API_URL with SPLUNK_AO_CONSOLE_…
adityamehra Jun 26, 2026
c5393ed
fix(ci): Update install uv
adityamehra Jun 26, 2026
9972409
fix(ci): remove uv toml which points to pypi index
adityamehra Jun 26, 2026
99697dd
fix(docs): remove Galileo reference
adityamehra Jun 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions .github/workflows/ci-tests-splunk-ao-a2a.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Test splunk-ao-a2a

on:
push:
branches: [main]
paths:
- 'splunk-ao-a2a/**'
- '.github/workflows/ci-tests-splunk-ao-a2a.yaml'
pull_request:
paths:
- 'splunk-ao-a2a/**'
- '.github/workflows/ci-tests-splunk-ao-a2a.yaml'

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
test:
name: Python ${{ matrix.python-version }}
strategy:
fail-fast: false
matrix:
python-version: ["3.11", "3.12", "3.13", "3.14"]

runs-on: ubuntu-latest
# Hard cap per matrix job to bail out fast on real hangs.
timeout-minutes: 30

defaults:
run:
working-directory: splunk-ao-a2a

steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
with:
python-version: ${{ matrix.python-version }}

- name: Install uv
uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
with:
enable-cache: true
cache-dependency-glob: "**/splunk-ao-a2a/pyproject.toml"

# uv sources in pyproject.toml pins splunk-ao to the local monorepo root
# as an editable install, so this always tests against the latest local code.
- name: Install dependencies
run: uv sync --dev

- name: Show installed versions
run: uv pip list | grep -E "^(galileo|a2a-sdk|splunk-ao)"

- name: Run type check
run: uv run mypy src/

- name: Run tests
run: uv run pytest --cov=splunk_ao_a2a --cov-report=xml
5 changes: 0 additions & 5 deletions galileo-a2a/examples/.env.example

This file was deleted.

4 changes: 0 additions & 4 deletions galileo-a2a/src/galileo_a2a/__init__.py

This file was deleted.

1 change: 0 additions & 1 deletion galileo-a2a/src/galileo_a2a/_version.py

This file was deleted.

File renamed without changes.
47 changes: 24 additions & 23 deletions galileo-a2a/README.md → splunk-ao-a2a/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# galileo-a2a
# splunk-ao-a2a

[![PyPI version](https://img.shields.io/pypi/v/galileo-a2a.svg)](https://pypi.org/project/galileo-a2a/)
[![Python versions](https://img.shields.io/pypi/pyversions/galileo-a2a.svg)](https://pypi.org/project/galileo-a2a/)
[![License](https://img.shields.io/pypi/l/galileo-a2a.svg)](https://github.com/rungalileo/galileo-python/blob/main/LICENSE)
[![PyPI version](https://img.shields.io/pypi/v/splunk-ao-a2a.svg)](https://pypi.org/project/splunk-ao-a2a/)
[![Python versions](https://img.shields.io/pypi/pyversions/splunk-ao-a2a.svg)](https://pypi.org/project/splunk-ao-a2a/)
[![License](https://img.shields.io/pypi/l/splunk-ao-a2a.svg)](https://github.com/splunk/splunk-ao-python/blob/main/LICENSE)

Galileo observability for [A2A (Agent-to-Agent)](https://github.com/google/A2A) protocol interactions. Automatic tracing of agent-to-agent calls, task lifecycle, and cross-agent distributed trace correlation.
Splunk AO observability for [A2A (Agent-to-Agent)](https://github.com/google/A2A) protocol interactions. Automatic tracing of agent-to-agent calls, task lifecycle, and cross-agent distributed trace correlation.

## How It Works

Expand All @@ -25,31 +25,31 @@ Galileo observability for [A2A (Agent-to-Agent)](https://github.com/google/A2A)
│ └─────────────────┬────────────────────────┘ │
│ │ │
│ ┌──────────▼──────────┐ │
│ │ Galileo │ │
│ │ Splunk AO │ │
│ │ (Trace Explorer) │ │
│ └─────────────────────┘ │
└──────────────────────────────────────────────────────────────────────┘
```

`galileo-a2a` instruments both the **client** (outbound calls) and **server** (inbound requests) sides of the A2A protocol. Trace context is propagated through A2A message metadata so all agents appear in a single distributed trace in Galileo.
`splunk-ao-a2a` instruments both the **client** (outbound calls) and **server** (inbound requests) sides of the A2A protocol. Trace context is propagated through A2A message metadata so all agents appear in a single distributed trace in Splunk AO.

## Installation

```bash
pip install galileo-a2a
pip install splunk-ao-a2a
```

**Requirements:** Python 3.10+, a [Galileo API key](https://www.rungalileo.io/), and [a2a-sdk](https://pypi.org/project/a2a-sdk/) 0.3+
**Requirements:** Python 3.11+, a [Splunk AO API key](https://www.splunk.com/), and [a2a-sdk](https://pypi.org/project/a2a-sdk/) 0.3+

## Quick Start

```python
from galileo.otel import GalileoSpanProcessor, add_splunk_ao_span_processor
from galileo_a2a import A2AInstrumentor
from splunk_ao.otel import SplunkAOSpanProcessor, add_splunk_ao_span_processor
from splunk_ao_a2a import A2AInstrumentor
from opentelemetry.sdk.trace import TracerProvider

provider = TracerProvider()
add_splunk_ao_span_processor(provider, GalileoSpanProcessor())
add_splunk_ao_span_processor(provider, SplunkAOSpanProcessor())
A2AInstrumentor().instrument(tracer_provider=provider, agent_name="orchestrator")
```

Expand All @@ -63,13 +63,14 @@ Once instrumented, all `a2a-sdk` client and server interactions produce OTel spa
| `agent_name` | Name of this agent, set on spans as `gen_ai.agent.name`. |
| `capture_content` | Set to `False` to disable capturing message content (e.g. for PII compliance). |

Environment variables for the Galileo exporter:
Environment variables for the Splunk AO exporter:

| Environment Variable | Description |
|---------------------|-------------|
| `GALILEO_API_KEY` | Galileo API key (required) |
| `GALILEO_PROJECT` | Project name (alternative to `GalileoSpanProcessor(project=...)`) |
| `GALILEO_LOG_STREAM` | Log stream name (alternative to `GalileoSpanProcessor(logstream=...)`) |
| `SPLUNK_AO_API_KEY` | Splunk AO API key (required) |
| `SPLUNK_AO_CONSOLE_URL` | Splunk AO console URL (required for self-hosted deployments, e.g. `http://localhost:8088`) |
| `SPLUNK_AO_PROJECT` | Project name (alternative to `SplunkAOSpanProcessor(project=...)`) |
| `SPLUNK_AO_LOG_STREAM` | Log stream name (alternative to `SplunkAOSpanProcessor(logstream=...)`) |

## Features

Expand All @@ -83,11 +84,11 @@ The instrumentor patches both sides of the A2A protocol:

### Cross-Agent Distributed Tracing

When Agent A calls Agent B, trace context is propagated through A2A message metadata. The receiving agent joins the caller's trace, so both agents appear in a single distributed trace in Galileo.
When Agent A calls Agent B, trace context is propagated through A2A message metadata. The receiving agent joins the caller's trace, so both agents appear in a single distributed trace in Splunk AO.

### Session Tracking

A2A's `context_id` is mapped to `session.id`, grouping all interactions within the same conversation into a Galileo session.
A2A's `context_id` is mapped to `session.id`, grouping all interactions within the same conversation into a Splunk AO session.

### Disabling Instrumentation

Expand Down Expand Up @@ -119,8 +120,8 @@ from a2a.types import (
AgentCapabilities, AgentCard, AgentSkill, Message, Role,
TaskState, TaskStatus, TaskStatusUpdateEvent, TextPart,
)
from splunk_ao.otel import GalileoSpanProcessor, add_splunk_ao_span_processor
from galileo_a2a import A2AInstrumentor
from splunk_ao.otel import SplunkAOSpanProcessor, add_splunk_ao_span_processor
from splunk_ao_a2a import A2AInstrumentor
from langchain.agents import create_agent
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
Expand All @@ -132,7 +133,7 @@ from typing_extensions import TypedDict

# ---- Only 4 lines needed for full distributed tracing ----
provider = TracerProvider()
add_splunk_ao_span_processor(provider, GalileoSpanProcessor())
add_splunk_ao_span_processor(provider, SplunkAOSpanProcessor())
A2AInstrumentor().instrument(tracer_provider=provider, agent_name="orchestrator")
LangchainInstrumentor().instrument(tracer_provider=provider)

Expand Down Expand Up @@ -255,13 +256,13 @@ async def main():
provider.shutdown()

if __name__ == "__main__":
# Set environment variables: GALILEO_API_KEY, OPENAI_API_KEY
# Set environment variables: SPLUNK_AO_API_KEY, OPENAI_API_KEY
asyncio.run(main())
```

## Resources

- [Galileo Documentation](https://v2docs.galileo.ai)
- [Splunk AO Documentation](https://docs.galileo.ai)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🟡 minor (documentation): This link was rebranded to "Splunk AO Documentation" but the URL still points at Galileo (https://docs.galileo.ai), and it was changed from the original v2docs.galileo.ai to docs.galileo.ai in the process. The label and target are now inconsistent, and the new host may not resolve. Point this at the actual Splunk AO docs (or revert the URL to the working Galileo one until a Splunk docs site exists).

Suggested change
- [Splunk AO Documentation](https://docs.galileo.ai)
- [Splunk AO Documentation](https://docs.splunk.com/observability)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@fercor-cisco this is in line with the discussion and what has been already done for examples and adk

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

agreed, we're keeping the previous URL for now

- [A2A Protocol Specification](https://a2a-protocol.org)
- [a2a-sdk Documentation](https://pypi.org/project/a2a-sdk)

Expand Down
5 changes: 5 additions & 0 deletions splunk-ao-a2a/examples/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
SPLUNK_AO_API_KEY=your-splunk-ao-key
SPLUNK_AO_CONSOLE_URL=https://<splunk-ao-console-host>
SPLUNK_AO_PROJECT=a2a-distributed-tracing-demo
SPLUNK_AO_LOG_STREAM=dev
OPENAI_API_KEY=your-openai-key

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

splunk-ao-a2a/examples/two_agent_demo.py:1-6 (line not in diff)

🟡 minor (documentation): Stale Galileo brand references remain in this example's module docstring (lines 1 and 6) and in the inline comment at line 60 ("# Galileo tracing setup"), even though the imports and package were rebranded to Splunk AO. Since this PR is the rebrand, update these to "Splunk AO" for consistency.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@fercor-cisco fixed!

Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"""Two-agent A2A demo with LangGraph orchestrator and Galileo distributed tracing.
"""Two-agent A2A demo with LangGraph orchestrator and Splunk AO distributed tracing.

Architecture:
Orchestrator (LangGraph) ──A2A──> Researcher (LangChain agent + search tool)

Both agents appear in a single distributed trace in Galileo.
Both agents appear in a single distributed trace in Splunk AO.

Usage:
# Copy and fill in the .env file:
Expand Down Expand Up @@ -52,12 +52,12 @@
from starlette.applications import Starlette
from typing_extensions import TypedDict

from galileo_a2a import A2AInstrumentor
from splunk_ao_a2a import A2AInstrumentor

load_dotenv(Path(__file__).parent / ".env")

# ---------------------------------------------------------------------------
# Galileo tracing setup
# Splunk AO tracing setup
# ---------------------------------------------------------------------------

provider = TracerProvider()
Expand Down
36 changes: 18 additions & 18 deletions galileo-a2a/pyproject.toml → splunk-ao-a2a/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
[project]
name = "galileo-a2a"
version = "1.0.0"
description = "Galileo observability auto-instrumentation for A2A (Agent-to-Agent) protocol"
name = "splunk-ao-a2a"
version = "0.1.0"
description = "Splunk AO observability auto-instrumentation for A2A (Agent-to-Agent) protocol"
readme = "README.md"
requires-python = ">=3.11,<3.15"
license = { text = "Apache-2.0" }
authors = [{ name = "Galileo Technologies Inc.", email = "team@galileo.ai" }]
authors = [{ name = "Splunk Inc.", email = "team@splunk.com" }]
classifiers = [
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python :: 3",
Expand All @@ -14,18 +14,18 @@ classifiers = [
"Programming Language :: Python :: 3.13",
]
dependencies = [
"galileo>=1.47.0,<2.0.0",
"splunk-ao>=0.1.0,<1.0.0",
"a2a-sdk>=0.3.0,<1.0.0",
"opentelemetry-api>=1.38.0",
"opentelemetry-sdk>=1.38.0",
]

[project.urls]
Repository = "https://github.com/rungalileo/galileo-python"
Repository = "https://github.com/splunk/splunk-ao-python"

# UV-specific configuration (path for dev, ignored when installed from PyPI)
[tool.uv]
sources = { galileo = { path = "../", editable = true } }
sources = { "splunk-ao" = { path = "../", editable = true } }

[dependency-groups]
dev = [
Expand All @@ -37,7 +37,7 @@ dev = [
"ruff>=0.12.3",
"mypy>=1.16.0",
"opentelemetry-instrumentation>=0.61b0",
"galileo[otel]>=1.47.0",
"splunk-ao[otel]>=0.1.0,<1.0.0",
]
examples = [
"uvicorn>=0.42.0",
Expand All @@ -57,7 +57,7 @@ requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/galileo_a2a"]
packages = ["src/splunk_ao_a2a"]

[tool.pytest.ini_options]
testpaths = ["tests"]
Expand All @@ -68,10 +68,10 @@ python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
env = [
"GALILEO_CONSOLE_URL=http://fake.test:8088",
"GALILEO_API_KEY=api-1234567890",
"GALILEO_PROJECT=test-project",
"GALILEO_LOG_STREAM=test-log-stream",
"SPLUNK_AO_CONSOLE_URL=http://fake.test:8088",
"SPLUNK_AO_API_KEY=api-1234567890",
"SPLUNK_AO_PROJECT=test-project",
"SPLUNK_AO_LOG_STREAM=test-log-stream",
]
addopts = [
"-v",
Expand All @@ -94,7 +94,7 @@ ignore = ["ARG001", "ARG002", "D"]
"tests/**/*.py" = ["ARG", "D"]

[tool.ruff.lint.isort]
known-first-party = ["galileo_a2a", "galileo"]
known-first-party = ["splunk_ao_a2a", "splunk_ao"]

[tool.mypy]
python_version = "3.11"
Expand All @@ -105,7 +105,7 @@ ignore_missing_imports = true
follow_imports = "skip"

[tool.coverage.run]
source = ["src/galileo_a2a"]
source = ["src/splunk_ao_a2a"]
omit = ["tests/*"]

[tool.coverage.report]
Expand All @@ -119,11 +119,11 @@ exclude_lines = [
]

[tool.semantic_release]
version_variables = ["src/galileo_a2a/_version.py:__version__"]
version_variables = ["src/splunk_ao_a2a/_version.py:__version__"]
version_toml = ["pyproject.toml:project.version"]
tag_format = "galileo-a2a-v{version}"
tag_format = "splunk-ao-a2a-v{version}"
version_source = "tag"
commit_message = "chore(release): galileo-a2a v{version}\n\nAutomatically generated by python-semantic-release"
commit_message = "chore(release): splunk-ao-a2a v{version}\n\nAutomatically generated by python-semantic-release"

[tool.semantic_release.commit_parser_options]
patch_tags = ["fix", "perf", "chore", "docs", "style", "refactor"]
Expand Down
4 changes: 4 additions & 0 deletions splunk-ao-a2a/src/splunk_ao_a2a/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from splunk_ao_a2a._version import __version__
from splunk_ao_a2a.instrumentor import A2AInstrumentor

__all__ = ["A2AInstrumentor", "__version__"]
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
from opentelemetry import trace
from opentelemetry.trace import StatusCode, Tracer

from galileo_a2a._constants import GALILEO_OBSERVE_KEY
from galileo_a2a._context import inject_trace_context, iter_with_context
from galileo_a2a._spans import (
from splunk_ao_a2a._constants import SPLUNK_AO_OBSERVE_KEY
from splunk_ao_a2a._context import inject_trace_context, iter_with_context
from splunk_ao_a2a._spans import (
set_client_attributes,
set_input,
set_simple_input,
Expand Down Expand Up @@ -107,7 +107,7 @@ async def wrapper(
otel_context.detach(token)

request_metadata = dict(request_metadata) if request_metadata else {}
request_metadata[GALILEO_OBSERVE_KEY] = observe_ctx
request_metadata[SPLUNK_AO_OBSERVE_KEY] = observe_ctx

result = original(
self,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
"""Constants for galileo-a2a instrumentation."""
"""Constants for splunk-ao-a2a instrumentation."""

# Instrumentor identity
from galileo_a2a._version import __version__
from splunk_ao_a2a._version import __version__

INSTRUMENTOR_NAME = "galileo-a2a"
INSTRUMENTOR_NAME = "splunk-ao-a2a"
INSTRUMENTOR_VERSION = __version__

# Metadata keys for in-band trace context propagation
GALILEO_OBSERVE_KEY = "galileo_observe"
SPLUNK_AO_OBSERVE_KEY = "splunk_ao_observe"
AGNTCY_OBSERVE_KEY = "observe" # compatibility with AGNTCY Observe SDK

# A2A span attribute keys (match API-side A2A extension expectations)
Expand Down
Loading
Loading