Skip to main content

AAEP integration for agents built directly on the Anthropic Python SDK

Project description

Python Anthropic SDK Producer Example

AAEP integration with the official Anthropic Python SDK. This example demonstrates how to emit AAEP events from agents built directly on anthropic.Anthropic() and client.messages.stream(), without any agent framework.

If you're building Claude-powered agents using the Anthropic SDK and want AAEP support, this is the example to copy.


What this example demonstrates

  • Direct integration with client.messages.stream() and client.messages.create()
  • Native handling of Anthropic's streaming event format (content_block_delta, content_block_start, etc.)
  • Tool use translation: Anthropic's tool_use content blocks → AAEP agent.tool.invoked
  • Multi-turn conversation handling
  • Proper Claude model version reporting in producer.model
  • Streaming output with sentence-boundary coalescing
  • All 12 core AAEP event types in realistic Anthropic-API-driven usage

This example reuses the AAEPEmitter from python-minimal — same machinery, different integration. The Anthropic-specific code is just the adapter between Anthropic's API and the emitter.


When to use this pattern vs others

Pick this pattern when:

  • You use the Anthropic Python SDK directly
  • You want to leverage Anthropic's native tool use, prompt caching, or extended thinking
  • You don't need (or don't want) a framework abstraction

Pick python-langchain when: you already use LangChain (regardless of LLM provider).

Pick python-minimal when: you're building everything from scratch, including your own LLM client.


Installation

cd examples/producers/python-anthropic-sdk
pip install -e .

You'll need an Anthropic API key in your environment:

export ANTHROPIC_API_KEY="sk-ant-..."

Requires Python 3.10 or newer.


Quick start

import anthropic
from aaep_anthropic_sdk import AnthropicAAEPAdapter

# Step 1: Set up your Anthropic client normally
client = anthropic.Anthropic()

# Step 2: Wrap it with the AAEP adapter
def my_transport(event):
    """Send the event to subscribers (HTTP/SSE, WebSocket, etc.)"""
    print(event)  # in production: serialize and send

adapter = AnthropicAAEPAdapter(send_event=my_transport, model="claude-opus-4-7")

# Step 3: Run a session through the adapter
session_id = await adapter.run_session(
    user_message="Tell me about retirement planning.",
    tools=[
        {
            "name": "fetch_balance",
            "description": "Look up an account balance",
            "input_schema": {
                "type": "object",
                "properties": {"account": {"type": "string"}},
            },
        },
    ],
    tool_handlers={
        "fetch_balance": lambda account: f"Balance for {account}: $3,247.18",
    },
)

That's all. The adapter calls Claude, processes the streaming response, executes any tool_use blocks (with confirmation for irreversible tools), and emits AAEP events throughout.


Running the included demo

python -m aaep_anthropic_sdk.example_agent

This runs three example sessions (basic query, tool use, multi-turn) against Claude and prints every emitted AAEP event.

Note: the demo requires ANTHROPIC_API_KEY to be set. If not set, it falls back to a mock mode that doesn't call the real API.


Running the conformance suite against it

# Terminal 1: start the server (uses mock mode by default for portability)
python -m aaep_anthropic_sdk.server --port 8082

# Terminal 2: run conformance
aaep-conformance producer --endpoint http://localhost:8082 --level 2

The conformance suite drives the adapter with synthetic user prompts and verifies the resulting AAEP event streams.


Project layout

python-anthropic-sdk/
├── README.md
├── pyproject.toml
├── aaep_anthropic_sdk/
│   ├── __init__.py
│   ├── adapter.py             # AnthropicAAEPAdapter
│   ├── example_agent.py       # Runnable demo with real Anthropic API
│   └── server.py              # HTTP/SSE wrapper for conformance testing
└── tests/
    ├── __init__.py
    └── test_adapter.py

Key design decisions

1. The adapter directly consumes Anthropic's streaming events

Anthropic's client.messages.stream() returns a structured event stream:

  • message_start — model begins responding
  • content_block_start — new content block (text, tool_use, etc.)
  • content_block_delta — incremental update (text_delta, input_json_delta)
  • content_block_stop — content block done
  • message_delta — usage stats, stop_reason
  • message_stop — full message done

The adapter translates each into the appropriate AAEP event. Text deltas feed the StreamCoalescer; tool_use blocks become tool.invoked/tool.completed pairs; stop_reason informs the terminal event.

2. Tool use safety enforced before execution

When Claude emits a tool_use content block, the adapter:

  1. Emits agent.tool.invoked BEFORE calling the handler
  2. For irreversible or high-risk tools: emits agent.awaiting.confirmation and blocks on the reply
  3. Only executes the tool handler on decision: "accept"
  4. Emits agent.tool.completed with the result

This means an unsafe action (e.g., send_email) cannot execute without explicit user consent — regardless of what the model "wants" to do.

3. Model version included in producer

The adapter reports the exact Claude model version in producer.model, so subscribers know which model is responding (different models may need different verbosity treatment for accessibility). When using claude-opus-4-7, you'll see "model": "claude-opus-4-7" in every emitted event.

4. Same emitter as python-minimal

The adapter imports AAEPEmitter, StreamCoalescer, and make_id from the python-minimal package. Bug fixes propagate; safety guarantees are uniform across all examples.


See also

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aaep_anthropic_sdk_producer-1.0.0.tar.gz (19.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aaep_anthropic_sdk_producer-1.0.0-py3-none-any.whl (15.9 kB view details)

Uploaded Python 3

File details

Details for the file aaep_anthropic_sdk_producer-1.0.0.tar.gz.

File metadata

File hashes

Hashes for aaep_anthropic_sdk_producer-1.0.0.tar.gz
Algorithm Hash digest
SHA256 aea37d126f3a8d449ead25cdf1c49dbf593e17ff4e8e006025ee75959d91152a
MD5 2e2373864f66fbff8b47eb7ef8b295a5
BLAKE2b-256 278bb7bcb0ed61598deda0e4cc6de0129f324d3936ca10cbc4d71b6b200362cf

See more details on using hashes here.

File details

Details for the file aaep_anthropic_sdk_producer-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for aaep_anthropic_sdk_producer-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cbe13f336dd6a8b7d6f87578e82d45160d40202d5b8c3b55dd301a776bd46372
MD5 1cd9c7e6c3e95c9c91989bd86f31498d
BLAKE2b-256 1a6555f9118c9d3b73a72656b9ae60db5c557fed32aafe5db80a08d887f29f4d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page